using System; using System.Linq.Expressions; using Svelto.DataStructures; using Svelto.ECS; using Svelto.ECS.Internal; using TechbloxModdingAPI.Blocks; namespace TechbloxModdingAPI { public abstract class EcsObjectBase { public abstract EGID Id { get; } //Abstract to support the 'place' Block constructor protected internal EcsInitData InitData; /// /// Holds information needed to construct a component initializer /// protected internal struct EcsInitData { private FasterDictionary group; private EntityReference reference; public static implicit operator EcsInitData(EntityInitializer initializer) => new EcsInitData {group = GetInitGroup(initializer), reference = initializer.reference}; public EntityInitializer Initializer(EGID id) => new EntityInitializer(id, group, reference); public bool Valid => group != null; } private delegate FasterDictionary GetInitGroupFunc( EntityInitializer initializer); /// /// Accesses the group field of the initializer /// private static GetInitGroupFunc GetInitGroup = CreateAccessor("_group"); //https://stackoverflow.com/questions/55878525/unit-testing-ref-structs-with-private-fields-via-reflection private static TDelegate CreateAccessor(string memberName) where TDelegate : Delegate { var invokeMethod = typeof(TDelegate).GetMethod("Invoke"); if (invokeMethod == null) throw new InvalidOperationException($"{typeof(TDelegate)} signature could not be determined."); var delegateParameters = invokeMethod.GetParameters(); if (delegateParameters.Length != 1) throw new InvalidOperationException("Delegate must have a single parameter."); var paramType = delegateParameters[0].ParameterType; var objParam = Expression.Parameter(paramType, "obj"); var memberExpr = Expression.PropertyOrField(objParam, memberName); Expression returnExpr = memberExpr; if (invokeMethod.ReturnType != memberExpr.Type) returnExpr = Expression.ConvertChecked(memberExpr, invokeMethod.ReturnType); var lambda = Expression.Lambda(returnExpr, $"Access{paramType.Name}_{memberName}", new[] {objParam}); return lambda.Compile(); } } }