我正在处理一个带有委托类型和类型Action<Object[]>
的委托的函数,并创建一个给定类型的动态函数,如果调用它,则传递给定操作句柄的所有参数:
public static T GetEventDelegate<T>(Action<Object[]> handler) where T : class
{
if (!typeof(T).IsSubclassOf(typeof(Delegate)))
throw new Exception("T must be a delegate type");
Type[] argTypes = typeof(T).GetMethod("Invoke").GetParameters().Select((para) => para.ParameterType).ToArray();
List<ParameterExpression> lstArgs = new List<ParameterExpression>(
argTypes.Select((arg)=>Expression.Parameter(arg))
);
ParameterExpression result = Expression.Variable(typeof(Object[]));
var assignExpression = Expression.NewArrayInit(typeof(Object),lstArgs.ToArray());
var callExpression = Expression.Call(handler.Method, result);
var block = Expression.Block(
new List<ParameterExpression>(){result},
new Expression[]{assignExpression,callExpression}
);
var del = Expression.Lambda(block, lstArgs.ToArray()).Compile();
return Delegate.CreateDelegate(typeof(T), del, "Invoke") as T;
}
private static void testDel()
{
var del = GetEventDelegate<EventHandler>(
(x) =>
{
//Error, because x == null
Debug.Print(x.ToString());
}
);
del("testString", new EventArgs());
}
不幸的是,动作处理程序只传递了一个 null 值(参见testDel()
)。
你能帮我找一下错误吗?
提前致谢!
答案 0 :(得分:1)
您的问题是因为您将结果ParameterExpression初始化为Object类型,但实际上从未为其赋值。这几乎可以归结为(在调用compile之后):
void Func(arguments..)
{
Object result;
new object[](arguments...);
method(result);
}
您实际上从未使用assign表达式将数组分配给结果。
与您的问题无关,您可以在创建lambda时使用Expression.Lambda(),因为您具有泛型中的类型。