我已经通过地址模型(Expression<Func<Address, bool>> addressPred
)构建了一个谓词。现在我想将它与Person模型的谓词(Expression<Func<Person, bool>> personPred
)结合起来。模型示例如下:
public class Person
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string StreetName { get; set; }
}
如果我做的话
addressPred = addressPred.And(a => a.StreetName == "Foo bar");
然后将其与personPred结合使用,组合谓词将具有与
相同的语句combinedPred = combinedPred.And(a => a.Address.StreetName == "Foo bar");
combinedPredicate的类型为Person
我怎么能做到这一点?
修改
实际上,为了简单起见,模型更大,并且缩短了。我最终想要实现的是构建一次Address谓词,然后为Person创建一个具有自己条件的谓词,然后将它组合成一个谓词,其中Person谓词的Address-part来自Address谓词(Address是一个属性)人)。我想这样做的原因是因为Address可能有很多条件,我想在进行db调用之前将它用作其他谓词(Person,后来也是Company,Customer等)的一部分(对于Person,公司,客户等)
此外,combinedPred
代码行仅用于显示来自地址谓词的combinedPred
的等价语句。
答案 0 :(得分:2)
情况是,构建的Expression<Func<Address, bool>> addressPred
的地址为ParameterExpression
,并且需要将表达式应用于MemberExpression
。因此,我建议将ParameterExpression
替换为MemberExpression
,例如:
var personParameter = Expression.Parameter(typeof(Person), "person");
var addressProperty = Expression.PropertyOrField(personParameter, "Address");
var combined = new ReplaceVisitor<Address>(addressProperty).Visit(addressPred.Body);
var result = Expression.Lambda<Func<Person, bool>>(combined, personParameter);
其中:
public class ReplaceVisitor<T> : ExpressionVisitor
{
private readonly MemberExpression _replacement;
public ReplaceVisitor(MemberExpression replacement)
{
_replacement = replacement;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return node.Type.IsAssignableFrom(typeof(T))
? _replacement : base.VisitParameter(node);
}
}