我正在写一个Expression引擎。传入一个对象,然后将对象的属性转化为一个Expression<Func<T,bool>>。
在下文中传入对象用Parameter替代。
我打算采用在 Parameter的属性上加Attribute的方法,来定义单个属性与该属性值之间的算术运算关系(==、>=、<=等)。
然而,我不知道采用什么方法,能够正确简洁的描述属性与属性之间的逻辑运算关系(&&、||)。
不知有人可否有思路?
将参数包装成表达式,然后Expression.And/Or
类1:
public class ParameterReset : ExpressionVisitor { private Dictionary<ParameterExpression, ParameterExpression> Dictionary { get; set; } public ParameterReset(Dictionary<ParameterExpression, ParameterExpression> dictionary) { this.Dictionary = dictionary ?? new Dictionary<ParameterExpression, ParameterExpression>(); } public static Expression ReplaceParameterList(Dictionary<ParameterExpression, ParameterExpression> dictionary, Expression expression) { return new ParameterReset(dictionary).Visit(expression); } protected override Expression VisitParameter(ParameterExpression param) { ParameterExpression replaceParam; if (Dictionary.TryGetValue(param, out replaceParam)) { param = replaceParam; } return base.VisitParameter(param); } }
添加类2
public static class ExpressionExtend { public static object Eval(this Expression expr) { return expr.Eval<object>(); } public static T Eval<T>(this Expression expr) { var constantExpr = expr as ConstantExpression; if (constantExpr != null) { return (T)constantExpr.Value; } var fun = Expression.Lambda<Func<object>>(Expression.Convert(expr, typeof(object))).Compile(); return (T)(fun()); } //整合两个表达式 public static Expression<T> Splice<T>(this Expression<T> left, Expression<T> right, Func<Expression, Expression, Expression> method) { var dictionary = left.Parameters.Select((f, i) => new { f, s = right.Parameters[i] }).ToDictionary(p => p.s, p => p.f); //替换参数 var secondBody = ParameterReset.ReplaceParameterList(dictionary, right.Body); return Expression.Lambda<T>(method(left.Body, secondBody), left.Parameters); } }
使用的时候
表达式1.Splice(表达式2, Expression.OrElse);
表达式1.Splice(表达式2, Expression.AndAlso);
把这个用运算符重载就可以达到了。like this
public static QueryCondition<T> operator &(QueryCondition<T> condition, Expression<Func<T, bool>> right) { if (condition != null && condition.Where != null) { condition.Where = condition.Where.Splice(right, Expression.AndAlso); } else { condition.Where = right; } return condition; } public static QueryCondition<T> operator |(QueryCondition<T> condition, Expression<Func<T, bool>> right) { if (condition != null && condition.Where != null) { condition.Where = condition.Where.Splice(right, Expression.OrElse); } else { condition.Where = right; } return condition; }
先谢谢您的答复,我先领域一下您的想法。