使用表达式树传递值不起作用

时间:2012-06-27 13:30:39

标签: c# reflection expression-trees

我正在处理一个带有委托类型和类型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())。

你能帮我找一下错误吗?

提前致谢!

1 个答案:

答案 0 :(得分:1)

您的问题是因为您将结果ParameterExpression初始化为Object类型,但实际上从未为其赋值。这几乎可以归结为(在调用compile之后):

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

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

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