diff --git a/Svelto.ECS/ComponentBuilder.CheckFields.cs b/Svelto.ECS/ComponentBuilder.CheckFields.cs
index 6ff8372..e09f38d 100644
--- a/Svelto.ECS/ComponentBuilder.CheckFields.cs
+++ b/Svelto.ECS/ComponentBuilder.CheckFields.cs
@@ -4,23 +4,22 @@ using System.Diagnostics;
#endif
using System;
using System.Reflection;
+using System.Text;
+using Svelto.Common;
namespace Svelto.ECS
{
internal static class ComponentBuilderUtilities
{
- const string MSG = "Entity Structs field and Entity View Struct components must hold value types.";
-
+ const string MSG = "Entity Components and Entity View Components fields cannot hold managed fields outside the Svelto rules.";
#if DISABLE_CHECKS
[Conditional("_CHECKS_DISABLED")]
#endif
public static void CheckFields(Type entityComponentType, bool needsReflection, bool isStringAllowed = false)
{
- if (entityComponentType == ENTITY_STRUCT_INFO_VIEW ||
- entityComponentType == EGIDType ||
- entityComponentType == EXCLUSIVEGROUPSTRUCTTYPE ||
- entityComponentType == SERIALIZABLE_ENTITY_STRUCT)
+ if (entityComponentType == ENTITY_STRUCT_INFO_VIEW || entityComponentType == EGIDType ||
+ entityComponentType == EXCLUSIVEGROUPSTRUCTTYPE || entityComponentType == SERIALIZABLE_ENTITY_STRUCT)
{
return;
}
@@ -29,7 +28,7 @@ namespace Svelto.ECS
{
if (entityComponentType.IsClass)
{
- throw new EntityComponentException("EntityComponents must be structs.", entityComponentType);
+ throw new ECSException("EntityComponents must be structs.", entityComponentType);
}
FieldInfo[] fields = entityComponentType.GetFields(BindingFlags.Public | BindingFlags.Instance);
@@ -48,51 +47,73 @@ namespace Svelto.ECS
if (fields.Length < 1)
{
- ProcessError("No valid fields found in Entity View Struct", entityComponentType);
+ ProcessError("No valid fields found in Entity View Components", entityComponentType);
}
for (int i = fields.Length - 1; i >= 0; --i)
{
FieldInfo fieldInfo = fields[i];
- if (fieldInfo.FieldType.IsInterfaceEx() == false && fieldInfo.FieldType.IsValueTypeEx() == false)
+ if (fieldInfo.FieldType.IsInterfaceEx() == true)
{
- ProcessError("Entity View Structs must hold only public interfaces or value type fields.",
- entityComponentType);
- }
-
- PropertyInfo[] properties = fieldInfo.FieldType.GetProperties(
- BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
+ PropertyInfo[] properties = fieldInfo.FieldType.GetProperties(
+ BindingFlags.Public | BindingFlags.Instance
+ | BindingFlags.DeclaredOnly);
- for (int j = properties.Length - 1; j >= 0; --j)
- {
- if (properties[j].PropertyType.IsGenericType)
+ for (int j = properties.Length - 1; j >= 0; --j)
{
- Type genericTypeDefinition = properties[j].PropertyType.GetGenericTypeDefinition();
- if (genericTypeDefinition == DISPATCHONSETTYPE ||
- genericTypeDefinition == DISPATCHONCHANGETYPE)
+ if (properties[j].PropertyType.IsGenericType)
{
- continue;
+ Type genericTypeDefinition = properties[j].PropertyType.GetGenericTypeDefinition();
+ if (genericTypeDefinition == DISPATCHONSETTYPE
+ || genericTypeDefinition == DISPATCHONCHANGETYPE)
+ {
+ continue;
+ }
}
- }
- Type propertyType = properties[j].PropertyType;
- if (propertyType != STRINGTYPE)
- {
+ Type propertyType = properties[j].PropertyType;
+
//for EntityComponentStructs, component fields that are structs that hold strings
//are allowed
SubCheckFields(propertyType, entityComponentType, isStringAllowed: true);
}
}
+ else
+ if (fieldInfo.FieldType.IsUnmanagedEx() == true)
+ {
+ SubCheckFields(fieldInfo.FieldType, entityComponentType, isStringAllowed);
+ }
+ else
+ {
+ ProcessError("Entity View Components must hold only public interfaces, strings or unmanaged type fields.",
+ entityComponentType);
+
+ }
}
}
}
+ static bool IsString(Type type)
+ {
+ return type == STRINGTYPE || type == STRINGBUILDERTYPE;
+ }
+
+ ///
+ /// This method checks the fields if it's an IEntityComponent, but checks all the properties if it's
+ /// IEntityViewComponent
+ ///
+ ///
+ ///
+ ///
static void SubCheckFields(Type fieldType, Type entityComponentType, bool isStringAllowed = false)
{
- if (fieldType.IsPrimitive || fieldType.IsValueType || (isStringAllowed == true && fieldType == STRINGTYPE))
+ //pass if it's Primitive or C# 8 unmanaged, or it's a string and string are allowed
+ //this check must allow pointers are they are unmanaged types
+ if ((isStringAllowed == true && IsString(fieldType) == true) || fieldType.IsUnmanagedEx() == true)
{
- if (fieldType.IsValueType && !fieldType.IsEnum && fieldType.IsPrimitive == false)
+ //if it's a struct we have to check the fields recursively
+ if (IsString(fieldType) == false && !fieldType.IsEnum && fieldType.IsPrimitive == false)
{
CheckFields(fieldType, false, isStringAllowed);
}
@@ -107,10 +128,10 @@ namespace Svelto.ECS
{
if (fieldType != null)
{
- throw new EntityComponentException(message, entityComponentType, fieldType);
+ throw new ECSException(message, entityComponentType, fieldType);
}
- throw new EntityComponentException(message, entityComponentType);
+ throw new ECSException(message, entityComponentType);
}
static readonly Type DISPATCHONCHANGETYPE = typeof(DispatchOnChange<>);
@@ -119,20 +140,8 @@ namespace Svelto.ECS
static readonly Type EXCLUSIVEGROUPSTRUCTTYPE = typeof(ExclusiveGroupStruct);
static readonly Type SERIALIZABLE_ENTITY_STRUCT = typeof(SerializableEntityComponent);
static readonly Type STRINGTYPE = typeof(string);
+ static readonly Type STRINGBUILDERTYPE = typeof(System.Text.StringBuilder);
internal static readonly Type ENTITY_STRUCT_INFO_VIEW = typeof(EntityInfoViewComponent);
}
-
- public class EntityComponentException : Exception
- {
- public EntityComponentException(string message, Type entityComponentType, Type type) :
- base(message.FastConcat(" entity view: '", entityComponentType.ToString(), "', field: '", type.ToString()))
- {
- }
-
- public EntityComponentException(string message, Type entityComponentType) :
- base(message.FastConcat(" entity view: ", entityComponentType.ToString()))
- {
- }
- }
}
\ No newline at end of file
diff --git a/Svelto.ECS/ComponentBuilder.cs b/Svelto.ECS/ComponentBuilder.cs
index f36c1c8..7089576 100644
--- a/Svelto.ECS/ComponentBuilder.cs
+++ b/Svelto.ECS/ComponentBuilder.cs
@@ -76,7 +76,7 @@ namespace Svelto.ECS
IS_ENTITY_VIEW_COMPONENT = typeof(IEntityViewComponent).IsAssignableFrom(ENTITY_COMPONENT_TYPE);
HAS_EGID = typeof(INeedEGID).IsAssignableFrom(ENTITY_COMPONENT_TYPE);
ENTITY_COMPONENT_NAME = ENTITY_COMPONENT_TYPE.ToString();
- var IS_UNMANAGED = ENTITY_COMPONENT_TYPE.IsUnmanaged();
+ var IS_UNMANAGED = ENTITY_COMPONENT_TYPE.IsUnmanagedEx();
if (IS_UNMANAGED)
EntityComponentIDMap.Register(new Filler());
@@ -89,7 +89,7 @@ namespace Svelto.ECS
EntityViewComponentCache.InitCache();
else
{
- if (ENTITY_COMPONENT_TYPE != ComponentBuilderUtilities.ENTITY_STRUCT_INFO_VIEW && ENTITY_COMPONENT_TYPE.IsUnmanaged() == false)
+ if (ENTITY_COMPONENT_TYPE != ComponentBuilderUtilities.ENTITY_STRUCT_INFO_VIEW && ENTITY_COMPONENT_TYPE.IsUnmanagedEx() == false)
throw new Exception($"Entity Component check failed, unexpected struct type (must be unmanaged) {ENTITY_COMPONENT_TYPE}");
}
}
diff --git a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs
index 2bc30e0..73a9229 100644
--- a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs
+++ b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs
@@ -13,7 +13,7 @@ namespace Svelto.ECS.Internal
static readonly bool _hasEgid = typeof(INeedEGID).IsAssignableFrom(_type);
internal static readonly bool _isUmanaged =
- _type.IsUnmanaged() && (typeof(IEntityViewComponent).IsAssignableFrom(_type) == false);
+ _type.IsUnmanagedEx() && (typeof(IEntityViewComponent).IsAssignableFrom(_type) == false);
internal SveltoDictionary>, ManagedStrategy> implMgd;
internal SveltoDictionary>, NativeStrategy> implUnmgd;
diff --git a/Svelto.ECS/ECSException.cs b/Svelto.ECS/ECSException.cs
index b815f84..34951fe 100644
--- a/Svelto.ECS/ECSException.cs
+++ b/Svelto.ECS/ECSException.cs
@@ -9,5 +9,15 @@ namespace Svelto.ECS
public ECSException(string message, Exception innerE):base("".FastConcat(message, ""), innerE)
{}
+
+ public ECSException(string message, Type entityComponentType, Type type) :
+ base(message.FastConcat(" entity view: '", entityComponentType.Name, "', field: '", type.Name))
+ {
+ }
+
+ public ECSException(string message, Type entityComponentType) :
+ base(message.FastConcat(" entity view: ", entityComponentType.Name))
+ {
+ }
}
}
\ No newline at end of file
diff --git a/Svelto.ECS/GlobalTypeID.cs b/Svelto.ECS/GlobalTypeID.cs
index 70d1fb7..b19f813 100644
--- a/Svelto.ECS/GlobalTypeID.cs
+++ b/Svelto.ECS/GlobalTypeID.cs
@@ -23,7 +23,7 @@ namespace Svelto.ECS
{
static Filler()
{
- DBC.ECS.Check.Require(UnmanagedTypeExtensions.IsUnmanaged() == true, "invalid type used");
+ DBC.ECS.Check.Require(UnmanagedTypeExtensions.IsUnmanagedEx() == true, "invalid type used");
}
//it's an internal interface