0

我正在研究一个函数,它接受一个委托类型和一个类型的委托,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());
    }

不幸的是,动作处理程序只传递了一个testDel()值(请参阅 参考资料)。

你能帮我找出错误吗?

提前致谢!

4

1 回答 1

1

您的问题是因为您将结果 ParameterExpression 初始化为 Object 类型,但从未实际为其分配值。这几乎编译成(在调用编译之后)是:

void Func(arguments..)
{
   Object result;
   new object[](arguments...);
   method(result);
}

您从未使用分配表达式将数组实际分配给结果。

与您的问题无关,您可以在创建 lambda 时使用 Expression.Lambda() 因为您具有泛型的类型。

于 2012-06-27T13:46:02.007 回答