using System;
using System.Linq.Expressions;
using Svelto.DataStructures;
using Svelto.ECS;
using Svelto.ECS.Internal;
namespace GamecraftModdingAPI.Blocks
{
public partial class BlockEngine
{
///
/// Holds information needed to construct a component initializer
///
internal struct BlockInitData
{
public FasterDictionary, ITypeSafeDictionary> Group;
}
internal delegate FasterDictionary, ITypeSafeDictionary> GetInitGroup(
EntityComponentInitializer initializer);
///
/// Accesses the group field of the initializer
///
internal GetInitGroup InitGroup = CreateAccessor("_group");
//https://stackoverflow.com/questions/55878525/unit-testing-ref-structs-with-private-fields-via-reflection
internal 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();
}
}
}