|
- using System;
- using System.Linq.Expressions;
-
- using Svelto.DataStructures;
- using Svelto.ECS;
- using Svelto.ECS.Internal;
-
- namespace GamecraftModdingAPI.Blocks
- {
- public partial class BlockEngine
- {
- /// <summary>
- /// Holds information needed to construct a component initializer
- /// </summary>
- internal struct BlockInitData
- {
- public FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> Group;
- }
-
- internal delegate FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> GetInitGroup(
- EntityComponentInitializer initializer);
-
- /// <summary>
- /// Accesses the group field of the initializer
- /// </summary>
- internal GetInitGroup InitGroup = CreateAccessor<GetInitGroup>("_group");
-
- //https://stackoverflow.com/questions/55878525/unit-testing-ref-structs-with-private-fields-via-reflection
- internal static TDelegate CreateAccessor<TDelegate>(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<TDelegate>(returnExpr, $"Access{paramType.Name}_{memberName}", new[] {objParam});
- return lambda.Compile();
- }
- }
- }
|