表达式树出错:System.InvalidOperationException:variable' message'类型' A'从范围''引用,但未定义

时间:2016-05-05 15:08:30

标签: c# .net code-generation expression-trees

我需要构建代表此代码的Action(new P()).Handle(argument type of A)

我有一个表达式:

Expression.Lambda<Action<A>>(Expression.Call(Expression.New(typeof(P)),
typeof(P).GetMethod("Handle", 
  BindingFlags.Instance | BindingFlags.Public), 
  Expression.Parameter(typeof(A), 
  "message")), 
Expression.Parameter(typeof(A), "message"))
.Compile();

但是当我尝试编译它时,它会抛出一个错误。错误是:

  

System.TypeInitializationException:&#39; PerformanceBenchma的类型初始值设定项   rk.Test&#39;抛出一个例外。 ---&GT; System.InvalidOperationException:变量&#39; message&#39;类型&#39; PerformanceBenchmark.A&#39;从范围&#39;&#39;引用,但事实并非如此   定义

我的代码如下所示:

public class A
{
}

public interface IInt<T>
{
    void Handle(T item);
}

public class P : IInt<A>
{
    public void Handle(A item)
    {
        return;
    }
}

public class Test
{
    public static readonly Action<A> _expr = Expression.Lambda<Action<A>>(Expression.Call(Expression.New(typeof(P)), typeof(P).GetMethod("Handle", BindingFlags.Instance | BindingFlags.Public), Expression.Parameter(typeof(A), "message")), Expression.Parameter(typeof(A), "message")).Compile(); 
}

我的目标是衡量_expr(new A())呼叫的速度。但是现在它在表达式编译方面失败了。

1 个答案:

答案 0 :(得分:1)

问题是你要两次调用Expression.Parameter,所以你有两个不同的参数表达式。不幸的是,它们没有按名称绑定。

因此解决方案只是使用多个语句,创建ParameterExpression 一次然后再使用两次。代码也更容易阅读:

var method = typeof(P).GetMethod("Handle", BindingFlags.Instance | BindingFlags.Public);
var parameter = Expression.Parameter(typeof(A), "message");
var ctorCall = Expression.New(typeof(P));
var methodCall = Expression.Call(ctorCall, method, parameter);
var expressionTree = Expression.Lambda<Action<A>>(methodCall, parameter);
var compiled = expressionTree.Compile();

当然要使用该代码初始化静态字段,您需要将其放在辅助方法或静态构造函数中。