52 lines
No EOL
2 KiB
C#
52 lines
No EOL
2 KiB
C#
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();
|
|
}
|
|
}
|
|
} |