通过使用类型参数的反射创建动作到代理调用
Creating Actions via reflection with type parameters to proxy call
给定一个简单的对象
public class Foo {
public void RunAction(Action<int, string, byte> action) {
Action(0, null, 0);
}
}
并给出了一个示例伪代码方法,该方法读取此 class 以通过反射获取操作类型:
public void DoProxy(object [] calledWithParameters) {
... some code ...
}
public void DoReflection(Foo foo) {
var actionParameterInfo = foo.getType().getMethod("RunAction").GetParameters()[0];
var parameterTypes = actionParameterInfo.ParameterType.GenericTypeArguments;
// Now I have the action type and the Type[] of the necessary parameters.
}
在这种情况下,我如何动态创建一个 Action 来使用调用时收到的参数调用我的 DoProxy?
您需要一个代码,在传递给代理之前将操作参数转换为数组。最简单的方法是使用一组具有不同数量通用参数的通用函数:
public static class ProxyCaller
{
public static Action<T1> CallProxy<T1>(Action<object[]> proxy) => new Action<T1>((T1 a1) => proxy(new object[] { a1 }));
public static Action<T1, T2> CallProxy<T1, T2>(Action<object[]> proxy) => new Action<T1, T2>((T1 a1, T2 a2) => proxy(new object[] { a1, a2 }));
public static Action<T1, T2, T3> CallProxy<T1, T2, T3>(Action<object[]> proxy) => new Action<T1, T2, T3>((T1 a1, T2 a2, T3 a3) => proxy(new object[] { a1, a2, a3 }));
// More of these if number of arguments can be 4, 5 etc.
public static object CreateAction(Action<object[]> proxy, Type[] parameterTypes)
{
var genericMethod = typeof(ProxyCaller).GetMethods().Where(m => m.Name == nameof(ProxyCaller.CallProxy) && m.GetGenericArguments().Length == parameterTypes.Length).First();
var method = genericMethod.MakeGenericMethod(parameterTypes);
var action = method.Invoke(null, new object[] { proxy });
return action;
}
}
然后在 DoReflection():
var parameterTypes = actionParameterInfo.ParameterType.GenericTypeArguments;
var action = ProxyCaller.CreateAction(DoProxy, parameterTypes);
// action has type Action<int, string, byte> here
给定一个简单的对象
public class Foo {
public void RunAction(Action<int, string, byte> action) {
Action(0, null, 0);
}
}
并给出了一个示例伪代码方法,该方法读取此 class 以通过反射获取操作类型:
public void DoProxy(object [] calledWithParameters) {
... some code ...
}
public void DoReflection(Foo foo) {
var actionParameterInfo = foo.getType().getMethod("RunAction").GetParameters()[0];
var parameterTypes = actionParameterInfo.ParameterType.GenericTypeArguments;
// Now I have the action type and the Type[] of the necessary parameters.
}
在这种情况下,我如何动态创建一个 Action 来使用调用时收到的参数调用我的 DoProxy?
您需要一个代码,在传递给代理之前将操作参数转换为数组。最简单的方法是使用一组具有不同数量通用参数的通用函数:
public static class ProxyCaller
{
public static Action<T1> CallProxy<T1>(Action<object[]> proxy) => new Action<T1>((T1 a1) => proxy(new object[] { a1 }));
public static Action<T1, T2> CallProxy<T1, T2>(Action<object[]> proxy) => new Action<T1, T2>((T1 a1, T2 a2) => proxy(new object[] { a1, a2 }));
public static Action<T1, T2, T3> CallProxy<T1, T2, T3>(Action<object[]> proxy) => new Action<T1, T2, T3>((T1 a1, T2 a2, T3 a3) => proxy(new object[] { a1, a2, a3 }));
// More of these if number of arguments can be 4, 5 etc.
public static object CreateAction(Action<object[]> proxy, Type[] parameterTypes)
{
var genericMethod = typeof(ProxyCaller).GetMethods().Where(m => m.Name == nameof(ProxyCaller.CallProxy) && m.GetGenericArguments().Length == parameterTypes.Length).First();
var method = genericMethod.MakeGenericMethod(parameterTypes);
var action = method.Invoke(null, new object[] { proxy });
return action;
}
}
然后在 DoReflection():
var parameterTypes = actionParameterInfo.ParameterType.GenericTypeArguments;
var action = ProxyCaller.CreateAction(DoProxy, parameterTypes);
// action has type Action<int, string, byte> here