ASP.Net MVC中有一个DisplayNameFor(x=>x.Title)
助手。
我想在行为中实现类似的东西。
我希望有一个方法接受基于User
类(u=>u.Birthdate
或u => u.Name)的表达式,一个操作数(大,小,等)和一个类似的值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)
更新:我创建了一个包含此问题解决方案的回购以及集合属性过滤 https://github.com/Alexander-Taran/Lambda-Magic-Filters
答案 0 :(得分:4)
这是否满足您的需求?
[TestClass]
public class UnitTest1
{
public Expression<Predicate<T>> GetFilterPredicate<T, R>(Expression<Func<T, R>> 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<Predicate<T>>(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; } }
答案 1 :(得分:3)
我相信这就是你的目标。
public Func<User, bool> MyMethod<TProperty>(Expression<Func<User, TProperty>> func, ComparisonPredicate op, TProperty value)
{
}
public enum ComparisonPredicate
{
Equal,
Unequal,
LessThan,
LessThanOrEqualTo,
GreaterThan,
GreaterThanOrEqualTo
}
答案 2 :(得分:0)
类似的东西:
Expression<Func<TObject, TProperty>> GenerateAssignExpression<TObject, TProperty>
(Expression<Func<TObject, TProperty>> 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<Func<TObject, TProperty>>(expAssign,
objectParameter,
valueParameter);
}
答案 3 :(得分:0)
以下方法将生成一个具有布尔返回值
的二进制表达式Expression<Predicate<TObject>>
GenerateAssignExpression<TObject, TProperty>(
Expression<Func<TObject, TProperty>> expression,
ExpressionType op,
TProperty Value)
{
return Expression.Lambda<Predicate<TObject>>(
Expression.MakeBinary(op, expression, Expression.Constant(Value)),
getExpression.Parameters[0]);
}
如果您希望使用泛型返回类型,只需将Predicate<TObject>
更改为Func<TObject,TReturn>
(您需要替换两个出现的`Predicate'