如何从Expression<Func<T>>构建Expression<Func<T,bool>>?

6

有没有一种方法可以从Expression<Func<T>>构建Expression<Func<T,bool>>

例如对于以下类:

public class MyClass
{
    public int Prop1{get;set;}
    public int Prop2{get;set;}
    public int Prop3{get;set;}
}

如果Expression<Func<T>>() => new MyClass{Prop2 = 5},那么结果应该是x => x.Prop2 == 5
如果Expression<Func<T>>() => new MyClass{Prop1 = 1, Prop3 = 3},那么结果应该是x => x.Prop1 == 1 && x.Prop3 == 3
换句话说,是否可能在运行时创建带有任意数量条件的函数?

您可以使用动态LINQ:http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx - AliRıza Adıyahşi
2个回答

7

就像这样:

static Expression<Func<T,bool>> Munge<T>(Expression<Func<T>> selector)
{
    var memberInit = selector.Body as MemberInitExpression;
    if (memberInit == null)
        throw new InvalidOperationException("MemberInitExpression is expected");
    var p = Expression.Parameter(typeof(T), "x");

    Expression body = null;
    foreach (MemberAssignment binding in memberInit.Bindings)
    {
        var comparer = Expression.Equal(
            Expression.MakeMemberAccess(p, binding.Member),
            binding.Expression);
        body = body == null ? comparer : Expression.AndAlso(body, comparer);
    }
    if (body == null) body = Expression.Constant(true);

    return Expression.Lambda<Func<T, bool>>(body, p);
}

2

让代码自己说话:

class Program
{
    static Expression<Func<T, bool>> Transform<T>(Expression<Func<T>> expression)
    {
        var initExpression = expression.Body as MemberInitExpression;
        if (initExpression == null)
        {
            throw new ArgumentException();
        }

        Expression bodyExpression = Expression.Constant(true);
        IEnumerable<MemberBinding> bindings = initExpression.Bindings;
        ParameterExpression param = Expression.Parameter(typeof(T));

        foreach (var memberBinding in bindings)
        {
            var memberAssigment = memberBinding as MemberAssignment;
            if (memberAssigment == null)
            {
                throw new ArgumentException();
            }

            var member = memberAssigment.Member;
            var value = memberAssigment.Expression;

            bodyExpression = Expression.AndAlso(
                bodyExpression,
                Expression.Equal(
                    Expression.MakeMemberAccess(param, member),
                    value
                )
            );
        }

        return Expression.Lambda<Func<T, bool>>(bodyExpression, param);
    }

    static void Main(string[] args)
    {
        Expression<Func<MyClass>> exp = () => new MyClass { Prop1 = 1, Prop3 = 3 };

        var result = Transform(exp);
        var lambda = result.Compile();

        var array = new[]
        {
            new MyClass { Prop1 = 1, Prop3 = 3 },
            new MyClass { Prop1 = 1, Prop2 = 2, Prop3 = 3 },
            new MyClass { Prop1 = 1, Prop3 = 1 },
            new MyClass { Prop1 = 3, Prop3 = 3 },
            new MyClass { Prop1 = 3, Prop3 = 1 },
            new MyClass()
        };

        foreach (var o in array)
        {
            Console.WriteLine(lambda(o));
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接