如何创建以表达式为参数的通用表达式 [英] How do I create a generic Expression that has an expression as a parameter

查看:91
本文介绍了如何创建以表达式为参数的通用表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

There is a DisplayNameFor(x=>x.Title) helper in ASP.Net MVC. I want to implement something similar in behavior.

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

I want to have a method that accepts an expression based on User class (u=>u.Birthdate or u=>u.Name), a operand (Greater, Less, Equal) and a value like DateTime.Now and returns an expression u=>u.Birthdate > DateTime.Now

我了解到,我将不得不从头开始手动构建结果表达式.我无法确定的是传递和处理属性表达式.

I understand that I'll have to build resulting expression manually from pieces. What i can't wrap my head around is passing in and handling of property expression.

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


I want to call a method like
GetFilterPredicate(u=>u.Birthdate,FilterOps.GreaterThan,DateTime.Parse("01.01.2013") or
GetFilterPredicate(u=>u.SomeIntProperty,FilterOps.Equals,2)

更新:我已经创建了一个仓库来解决这个问题,并且对集合属性进行了过滤 https://github.com/Alexander-Taran/Lambda-Magic-Filters

Update: I've created a repo with a solution to this question as well as a collection property filtering https://github.com/Alexander-Taran/Lambda-Magic-Filters

推荐答案

这是否满足您的需求?

Does this satisfy your needs ?

[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; } }

这篇关于如何创建以表达式为参数的通用表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆