我正在構建一個規則引擎,給我一些頭痛的問題。問題是當我嘗試建立表達式樹的構造如下:表達式樹編譯失敗,由於未定義的變量?
public Tuple<Expression, ParameterExpression> BuildExpression<T>(string propertyName, Enums.Operator ruleOperator,
ParameterExpression parameterExpression, List<object> values)
{
ParameterExpression listExpression = Expression.Parameter(typeof(List<object>));
ParameterExpression counterExpression = Expression.Parameter(typeof(int));
ParameterExpression toExpression = Expression.Parameter(typeof(int));
ParameterExpression arrayExpression = Expression.Parameter(typeof(object[]));
ParameterExpression valueExpression = Expression.Parameter(typeof(object));
ParameterExpression checkExpression = Expression.Parameter(typeof(T));
ParameterExpression returnExpression = Expression.Parameter(typeof(bool));
MemberExpression body = null;
foreach (var member in propertyName.Split('.'))
{
body = MemberExpression.Property(parameterExpression, member);
}
Expression expression = body.Expression;
var type = expression.Type;
ParameterExpression propertyExpression = Expression.Parameter(type);
ParameterExpression localPropertyExpression = Expression.Parameter(type);
LabelTarget breakLabel = Expression.Label();
PropertyInfo result = typeof(List<object>).GetProperty("Count");
MethodInfo toArray = typeof(List<object>).GetMethod("ToArray");
MethodInfo getGetMethod = result.GetGetMethod();
ConstantExpression constantExpression = Expression.Constant(true);
if (ruleOperator == Enums.Operator.NotFoundIn)
{
constantExpression = Expression.Constant(false);
}
Expression loop = Expression.Block(
new ParameterExpression[] { toExpression, arrayExpression, valueExpression, counterExpression,
returnExpression, propertyExpression, localPropertyExpression, listExpression },
Expression.Assign(listExpression, Expression.Constant(values)),
Expression.Assign(toExpression, Expression.Call(listExpression, getGetMethod)),
Expression.Assign(arrayExpression, Expression.Call(listExpression, toArray)),
Expression.Assign(propertyExpression, expression),
Expression.Loop(
Expression.IfThenElse(
Expression.LessThan(counterExpression, toExpression),
Expression.Block(
Expression.Assign(valueExpression, Expression.ArrayAccess(arrayExpression, counterExpression)),
Expression.Assign(localPropertyExpression, expression),
Expression.IfThen(
Expression.Equal(propertyExpression, localPropertyExpression),
Expression.Block(Expression.Assign(returnExpression, constantExpression),
Expression.Break(breakLabel))),
Expression.Assign(Expression.ArrayAccess(arrayExpression, counterExpression), checkExpression),
Expression.PostIncrementAssign(counterExpression)),
Expression.Break(breakLabel)
), breakLabel
),
Expression.And(returnExpression, constantExpression)
);
return new Tuple<Expression, ParameterExpression>(Expression.Block(loop), checkExpression);
}
這需要通過標準類定義的值的列表:
public class Criterion
{
public List<object> Values { get; set; }
public string PropertyName { get; set; }
public Enums.Operator Operator_ { get; set; }
}
,然後通過下面的方法編譯:
public Func<T, bool>[] CombineRules<T>(Criterion[] criteria)
{
var list = new List<Func<T, bool>>();
foreach (var criterion in criteria)
{
var expressionBuilder = new ExpressionBuilder();
var param = Expression.Parameter(typeof(T));
var expression =
expressionBuilder.BuildExpression<T>(criterion.PropertyName, criterion.Operator_, param, criterion.Values);
var func = Expression.Lambda<Func<T, bool>>(
expression.Item1, expression.Item2).Compile();
list.Add(func);
}
return list.ToArray();
}
但是,編譯失敗,出現以下異常:
System.InvalidOperationException: variable '' of type 'SnippInteractive.Web.Common.Models.V2.LineItem' referenced from scope '', but it is not defined
如果有人有任何有用的建議,我會非常感激。
感謝您的閱讀。
有與該代碼有很多潛在的問題,你能不能樣本手冊(即不使用'表達'方法)lambda呈現你正在嘗試構建的東西。 –