C#表达式组合
C# Expression composition
假设我有两个 类:
public class Parent {
public Child Child { get; set; }
}
public class Child {
public string Name { get; set; }
}
我想编写一个函数,通过包含子字符串的 child 名称过滤 Parents。
public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
return parents.Where(parent => parent.Child.Name.Contains(word));
}
如果我想取出那个表达式,这样我就可以在别处重复使用 Child 包含检查
public Expression<Func<Child, bool> ChildNameMatches(string word)
{
return child => child.Name.Contains(word));
}
然后如何在我的 .Where 中使用它以便我可以重写 ParentsChildNameMatches?
public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
return parents.Where( // how to leverage ChildNameMatches?
}
因此,给定一个 Expression<Func<Child, bool>>
,并且您可以通过 Child
属性 创建一个从 Parent
到 Child
的表达式Parent
class,你想获得一个Expression<Func<Parent, bool>>
.
您可以像这样使用 expression trees API, or you can use some 3rd party libraries like LinqKit 手动执行此操作:
public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
var childExpression = ChildNameMatches(word);
Expression<Func<Parent, bool>> expression = p => childExpression.Invoke(p.Child);
expression = expression.Expand();
return parents.Where(expression);
}
LinqKit 提供了 Invoke
方法,允许您将表达式组合在一起。它还提供了 Expand
方法来展平结果表达式。
您可以在此处阅读更多相关信息:http://www.albahari.com/nutshell/linqkit.aspx
已更新:之前的代码无效。固定。
您可以将您的 lambda 与 Invoke
结合使用
public static IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
var childPredicate = ChildNameMatches(word);
var parent = Expression.Parameter(typeof(Parent), "parent");
var parentPredicate = Expression.Lambda<Func<Parent, bool>>(
Expression.Invoke(
childPredicate,
Expression.Property(parent, "Child")),
parent);
return parents.Where(parentPredicate);
}
此代码将创建一个新表达式 parent => parent.Child
并将其用作 childPredicate
的参数
假设我有两个 类:
public class Parent {
public Child Child { get; set; }
}
public class Child {
public string Name { get; set; }
}
我想编写一个函数,通过包含子字符串的 child 名称过滤 Parents。
public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
return parents.Where(parent => parent.Child.Name.Contains(word));
}
如果我想取出那个表达式,这样我就可以在别处重复使用 Child 包含检查
public Expression<Func<Child, bool> ChildNameMatches(string word)
{
return child => child.Name.Contains(word));
}
然后如何在我的 .Where 中使用它以便我可以重写 ParentsChildNameMatches?
public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
return parents.Where( // how to leverage ChildNameMatches?
}
因此,给定一个 Expression<Func<Child, bool>>
,并且您可以通过 Child
属性 创建一个从 Parent
到 Child
的表达式Parent
class,你想获得一个Expression<Func<Parent, bool>>
.
您可以像这样使用 expression trees API, or you can use some 3rd party libraries like LinqKit 手动执行此操作:
public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
var childExpression = ChildNameMatches(word);
Expression<Func<Parent, bool>> expression = p => childExpression.Invoke(p.Child);
expression = expression.Expand();
return parents.Where(expression);
}
LinqKit 提供了 Invoke
方法,允许您将表达式组合在一起。它还提供了 Expand
方法来展平结果表达式。
您可以在此处阅读更多相关信息:http://www.albahari.com/nutshell/linqkit.aspx
已更新:之前的代码无效。固定。
您可以将您的 lambda 与 Invoke
public static IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
var childPredicate = ChildNameMatches(word);
var parent = Expression.Parameter(typeof(Parent), "parent");
var parentPredicate = Expression.Lambda<Func<Parent, bool>>(
Expression.Invoke(
childPredicate,
Expression.Property(parent, "Child")),
parent);
return parents.Where(parentPredicate);
}
此代码将创建一个新表达式 parent => parent.Child
并将其用作 childPredicate