friflo / Friflo.Json.Fliox

C# ECS + ORM
https://github.com/friflo/Friflo.Engine.ECS
GNU Lesser General Public License v3.0
165 stars 12 forks source link

Generic structs in components is not supported #45

Closed reejk closed 4 months ago

reejk commented 4 months ago

EntityStore cannot be initialized when adding a component that references a generic struct.

These types:

public struct GenericStruct<T>
{
    public T value;
}

public struct ComponentWithGenericStruct : IComponent
{
    public GenericStruct<int> gs;
}

Causing this exception:

System.TypeInitializationException : The type initializer for 'Static' threw an exception.
  ----> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
  ----> System.InvalidOperationException : invalid standard type. was: Tests.ECS.GenericStruct`1[System.Int32]
   at Friflo.Engine.ECS.ArchetypeConfig..ctor(EntityStoreBase store, Int32 archetypeIndex)
   at Friflo.Engine.ECS.EntityStoreBase.GetArchetypeConfig(EntityStoreBase store)
   at Friflo.Engine.ECS.EntityStoreBase..ctor()
   at Friflo.Engine.ECS.EntityStore..ctor(PidType pidType)
   at Friflo.Engine.ECS.EntityStore..ctor()
   at Tests.ECS.ExampleECS.ECS()
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
--TargetInvocationException
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Friflo.Engine.ECS.SchemaUtils.CreateSchemaType(Type type, TypeStore typeStore, SchemaTypes schemaTypes)
   at Friflo.Engine.ECS.SchemaUtils.RegisterSchemaTypes(TypeStore typeStore)
   at Friflo.Engine.ECS.EntityStoreBase.Static..cctor()
--InvalidOperationException
   at Friflo.Json.Fliox.Mapper.Map.PropField.GetTypeId(TypeMapper fieldType)
   at Friflo.Json.Fliox.Mapper.Map.PropField..ctor(String name, String jsonName, TypeMapper fieldType, FieldInfo field, PropertyInfo property, Member member, Int32 fieldIndex, Int32 genIndex, Boolean required, String docs)
   at Friflo.Json.Fliox.Mapper.Map.PropField`1..ctor(String name, String jsonName, TypeMapper fieldType, FieldInfo field, PropertyInfo property, Member member, Int32 fieldIndex, Int32 genIndex, Boolean required, String docs)
   at Friflo.Json.Fliox.Mapper.Map.Object.Reflect.FieldQuery`1.CreatePropField(Type type, String fieldName, PropertyInfo property, FieldInfo field, Boolean addMembers)
   at Friflo.Json.Fliox.Mapper.Map.Object.Reflect.FieldQuery`1.TraverseMembers(Type type, Boolean addMembers)
   at Friflo.Json.Fliox.Mapper.Map.Object.Reflect.FieldQuery`1..ctor(TypeStore typeStore, Type type, Type genClass, FieldFilter fieldFilter)
   at Friflo.Json.Fliox.Mapper.Map.Object.ClassMapper`1.InitTypeMapper(TypeStore typeStore)
   at Friflo.Json.Fliox.Mapper.TypeStore.GetTypeMapper(Type type)
   at Friflo.Json.Fliox.Mapper.TypeStore.GetTypeMapper[T]()
   at Friflo.Engine.ECS.SchemaUtils.CreateComponentType[T](TypeStore typeStore, Int32 structIndex)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
friflo commented 4 months ago

Thx, for report. Good case to reproduce.

Agree, this should be supported. Will have a look. As an instant workaround you can [Ignore] the field. See:

https://github.com/friflo/Friflo.Json.Fliox/blob/5219fe59d0c5f19a344b477e50ca91a080858dfe/Engine/Tests/ECS/Entity/Test_StructComponent.cs#L532

friflo commented 4 months ago

I came to the preliminary conclusion that the JSON Mapper (serializer) will ignore generic structs (and classes & interfaces) in future versions. Note: JSON Mapping is implemented in Friflo.Json.Fliox.

In case of generic classes / interfaces: Only known collection types - e.g. List<> or IList<> will be mapped.

friflo commented 4 months ago

Fixed the issue.

For now you need to reference the fixed nuget package or use the [Ignore] attribute.

<PackageReference Include="Friflo.Json.Fliox" Version="1.0.2" />

The next release of Friflo.Engine.ECS will include this version. Don't want to publish Friflo.Engine.ECS right now as I want to release Friflo.Engine.ECS v2.0.0 in the next two weeks.

More info at: https://github.com/friflo/Friflo.Json.Fliox/blob/991a335cb4565e68f1ac6c98e7a0e05dd7f20420/Engine/Tests/ECS/Entity/Test_StructComponent.cs#L519-L523

friflo commented 4 months ago

Fix is integrated in Tag engine-v2.0.0-preview.1 nuget Friflo.Engine.ECS/2.0.0-preview.1