Based on this old but very usefull article by the legendary Jon Skeet, I wrote a few methods to genereate Action Delegates from MethodInfos for faster invokations. But I ran into an issue, where I am unable to make any progress. See the example below:
public class DataContainer
{
public List<int> myList;
public DataContainer()
{
myList = new List<int>() { 1, 2, 3, 4 };
}
}
public static class ExtensionMethods
{
public static void DoStuff<T>(this IList<T> items)
{
}
}
public class Example
{
private Action<object> doStuffQuickly;
public void Test()
{
var fieldInfo = typeof(DataContainer).GetField("myList");
var doStuffMethod = typeof(ExtensionMethods).GetMethod("DoStuff", BindingFlags.Public | BindingFlags.Static);
var listType = typeof(IList<>).MakeGenericType(fieldInfo.FieldType.GenericTypeArguments);
doStuffQuickly = QuickAccess.CreateWeakActionWithOneParam(doStuffMethod, listType);
var data = new DataContainer();
var list = fieldInfo.GetValue(data);
doStuffQuickly(list);
}
}
public static class QuickAccess
{
private static MethodInfo _weak1ParamActionCreator;
private static MethodInfo Weak1ParamActionCreator => _weak1ParamActionCreator
??= typeof(QuickAccess).GetMethod(nameof(CreateWeakExplicit1ParamAction), BindingFlags.Static | BindingFlags.NonPublic);
public static Action<object> CreateWeakActionWithOneParam(MethodInfo methodInfo, Type paramType0 = null)
{
var parameters = methodInfo.GetParameters();
paramType0 ??= parameters[0].ParameterType;
var creationMethod = Weak1ParamActionCreator.MakeGenericMethod(paramType0);
return (Action<object>)creationMethod.Invoke(null, new object[] { methodInfo });
}
private static Action<object> CreateWeakExplicit1ParamAction<TValue>(MethodInfo methodInfo)
{
var action = CreateStrongExplicit1ParamAction<TValue>(methodInfo);
return (object value) => action((TValue)value);
}
private static Action<TValue> CreateStrongExplicit1ParamAction<TValue>(MethodInfo methodInfo)
{
//Debug.Log(methodInfo.GetParameters()[0].ParameterType.Name + " <-> " + typeof(TValue).Name);
//Debug.Log(PrintTypes(methodInfo.GetParameters()[0].ParameterType.GenericTypeArguments) + " <-> "
// + PrintTypes(typeof(TValue).GenericTypeArguments));
return (Action<TValue>)Delegate.CreateDelegate(typeof(Action<TValue>), methodInfo);
}
private static string PrintTypes(Type[] types)
{
return string.Join(", ", types.Select(t => t.Name));
}
}
This fails with ArgumentException: method arguments are incompatible
when trying to create the delegate. The commented logs print IList`1 <-> IList`1
and T <-> Int32
, which made me think that maybe
var listType = typeof(IList<>).MakeGenericType(fieldInfo.FieldType.GenericTypeArguments);
should instead simply be
var listType = typeof(IList<>);
but that is causing an InvalidOperationException: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
I don't know how to proceed from here. Any help will be appreciated.
Aucun commentaire:
Enregistrer un commentaire