Lambda编译抛出“从范围引用''类型的”变量“,但它没有定义”

时间:2013-05-02 16:11:18

标签: c# expression-trees runtime-compilation

当我尝试编译下面显示的lambda时,它会抛出:

类型为'System.Collections.Generic.IEnumerable`1 [WheelEndCatalogKendo.Models.SapBasicData]的变量'model''从范围''引用,但未定义

public static GridBoundColumnBuilder<TModel> BuildColumnString<TModel>(this GridBoundColumnBuilder<TModel> column, WebViewPage<IEnumerable<TModel>> webViewPage, int width) where TModel : class {
    var modelParameter = Expression.Parameter(typeof(IEnumerable<TModel>), "model");
    Expression<Func<IEnumerable<TModel>, TModel>> firstItem = (model) => model.FirstOrDefault();
    var member = MemberExpression.Property(firstItem.Body, column.Column.Member);
    var lambda = Expression.Lambda<Func<IEnumerable<TModel>, string>>(member, modelParameter);
    var title = webViewPage.Html.DisplayNameFor(lambda).ToHtmlString();
    var header = webViewPage.Html.ShortLabelFor(lambda).ToHtmlString().FixUpNewLinesAsHtml();
    var compiled = lambda.Compile(); //Throws here with "variable '...' of type '...' referenced from scope '', but it is not defined"
....
}

我看到几个类似的帖子;但到目前为止,他们还没有告诉我我的代码问题。看起来我正在提供lambda变量(作为第二个参数参数)。然而,我几乎没有创作表达树的经验。

有什么想法吗?

1 个答案:

答案 0 :(得分:9)

问题是model表达式中的firstItem参数与modelParameter不同。在表达式树中,参数不是按名称进行比较,而是通过引用进行比较。

这意味着最简单的解决方案是重用model中的firstItem参数,而不是创建自己的参数:

var modelParameter = firstItem.Parameters.Single();

通过此修改,您的代码将起作用。