用子Lambda表达式扩展Lambda表达式

时间:2019-04-15 16:18:27

标签: c# lambda expression

我试图找出是否有可能组合两个LambdaExpressions,其中一个lambda表达式使用第一个的Child属性。

给出以下两个类别:

class MyClass
{
    public string Name { get; set; }
    public SubClass Child { get; set; }
}

class SubClass
{
    public string SubClassName { get; set; }
}

以及以下表达式:

Expression<Func<MyClass, bool>> Expression1 = c => c.Name == "Test";

Expression<Func<SubClass, bool>> Expression2 = sc => sc.SubClassName == "SubTest";

我想将其组合为以下类型的lambda:

Expression<Func<MyClass, bool>> Combined;

原因是:上部的lambda是内部的,下部的lamba将由该方法的“用户”传递,该用户不知道(也不应该)MyClass存在,只知道SubClass。

这是否有可能,还是我应该找到另一条路可走?

1 个答案:

答案 0 :(得分:-1)

我不知道这是否正是你所追求的,但是;

public class Search
{
    private IEnumerable<MyClass> _data;

    public Search(IEnumerable<MyClass> data)
    {
        _data = data;
    }

    public IEnumerable<MyClass> Find(Expression<Func<SubClass, bool>> expr)
    {
        ParameterExpression x = Expression.Parameter(typeof(MyClass), "x");
        PropertyInfo p = typeof(MyClass).GetProperty("Child");

        var propertyExpression = (expr.Body as BinaryExpression).Left as MemberExpression;
        var constant = (expr.Body as BinaryExpression).Right;

        var memberAccess = Expression.MakeMemberAccess(x, p);
        var upperMemberAccess = Expression.MakeMemberAccess(memberAccess, propertyExpression.Member);

        var equals = Expression.Equal(upperMemberAccess, constant);

        var expression = Expression.Lambda<Func<MyClass, bool>>(equals, x);

        return _data.Where(expression.Compile());
    }
}

然后使用它就像这样;

var search = new Search(new[] {
        new MyClass { Name = "Test 1", Child = new SubClass { SubClassName = "Bob" }},
        new MyClass { Name = "Test 2", Child = new SubClass { SubClassName = "Subclass"}},
        new MyClass { Name = "Test 3", Child = new SubClass { SubClassName = "Subclass"}}
    });

    search.Find(k => k.SubClassName == "Subclass");

我敢肯定有一种更好的方法,因为这样做比较笨拙,但是从根本上讲,它将找到MyClass的所有具有名为“ Subclass”的子类的成员。它提取所传递的二进制表达式的成分(x => x.SubClassname ==“ Subclass”),并使用基于MyClass的equals重建新表达式。