When I attempt to compile the lambda shown below, it throws:
variable 'model' of type 'System.Collections.Generic.IEnumerable`1[WheelEndCatalogKendo.Models.SapBasicData]' referenced from scope '', but it is not defined
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"
....
}
I see several similar posts; but so far they haven't clued me in to the problem with my code. It seems like I am supplying the lambda variable (as the 2nd parameter argument). I have however almost no experience authoring expression trees.
Any ideas?
The problem is that the
model
parameter from thefirstItem
expression is not the same asmodelParameter
. In expression trees, parameters are not compared by name, but by reference.This means that the simplest solution is to reuse the
model
parameter fromfirstItem
, instead of creating your own parameter:With this modification, your code will work.