如何创建具有表达式作为参数的通用表达式

ASP.Net MVC中有一个DisplayNameFor(x=>x.Title)帮助器。 我想在行为中实现类似的东西。

我想有一个方法接受基于User类( u=>u.Birthdate或u => u.Name)的表达式,一个操作数(Greater,Less,Equal)和一个像DateTime.Now这样的值并返回一个表达式u=>u.Birthdate > DateTime.Now

我知道我必须手工构建结果表达式。 我无法包裹的是传递和处理属性表达。

编辑:
我想调用一个类似的方法
GetFilterPredicate(u=>u.Birthdate,FilterOps.GreaterThan,DateTime.Parse("01.01.2013")
GetFilterPredicate(u=>u.SomeIntProperty,FilterOps.Equals,2)

更新:我创建了一个包含此问题解决方案的repo以及一个集合属性过滤https://github.com/Alexander-Taran/Lambda-Magic-Filters

这满足了您的需求吗?

 [TestClass] public class UnitTest1 { public Expression> GetFilterPredicate(Expression> selector, FilterOps operand, R value) { var parameter = selector.Parameters[0]; var left = selector.Body; var right = Expression.Constant(value); var binaryExpression = Expression.MakeBinary(operand.ToExpressionType(), left, right); return Expression.Lambda>(binaryExpression, parameter); } [TestMethod] public void TestMethod1() { var p1 = this.GetFilterPredicate((User u) => u.Birthday.TimeOfDay.Hours, FilterOps.LessThan, 12); var p2 = this.GetFilterPredicate((User u) => u.Size, FilterOps.Equal, 180); var user = new User() { Birthday = new DateTime(2000, 1, 1), Size = 180 }; Assert.IsTrue(p1.Compile()(user)); Assert.IsTrue(p2.Compile()(user)); } } public enum FilterOps { GreaterThan, LessThan, Equal } public static class MyExtensions { public static ExpressionType ToExpressionType(this FilterOps operand) { switch (operand) { case FilterOps.GreaterThan: return ExpressionType.GreaterThan; case FilterOps.LessThan: return ExpressionType.LessThan; case FilterOps.Equal: return ExpressionType.Equal; default: throw new NotSupportedException(); } } } public class User { public DateTime Birthday { get; set; } public int Size { get; set; } } 

我相信这就是你的目标。

 public Func MyMethod(Expression> func, ComparisonPredicate op, TProperty value) { } public enum ComparisonPredicate { Equal, Unequal, LessThan, LessThanOrEqualTo, GreaterThan, GreaterThanOrEqualTo } 

像这样的东西:

 Expression> GenerateAssignExpression (Expression> getExpression, TProperty Value) { var getExpressionBody = getExpression.Body as MemberExpression; if (getExpressionBody == null) { throw new Exception("getExpressionBody is not MemberExpression: " + getExpression.Body); } var objectParameter = (ParameterExpression)getExpression.Parameters[0]; ConstantExpression constant = Expression.Constant(Value, typeof(TProperty)); var expAssign = Expression.Assign(e.Body, constant); return Expression.Lambda>(expAssign, objectParameter, valueParameter); } 

下面的方法将生成一个具有布尔返回值的二进制表达式

 Expression> GenerateAssignExpression( Expression> expression, ExpressionType op, TProperty Value) { return Expression.Lambda>( Expression.MakeBinary(op, expression, Expression.Constant(Value)), getExpression.Parameters[0]); } 

如果你想要一个generics返回类型只需将Predicate更改为Func (你需要替换’Predicate’的两个出现