我试图找出是否可以组合2个LambdaExpressions,其中一个lambda表达式使用第一个的Child属性。
鉴于以下2个类:
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将由方法的'user'传入,它不知道(也不应该)MyClass存在,只知道SubClass。
这是可能的,还是我应该找到另一条路?
我不知道这是不是你所追求的,但是;
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重建一个新表达式。