C#表达式组合

C#表达式组合,c#,lambda,expression,iqueryable,C#,Lambda,Expression,Iqueryable,假设我有两门课: public class Parent { public Child Child { get; set; } } public class Child { public string Name { get; set; } } 我想写一个函数,通过包含子字符串的孩子的名字过滤父母 public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, str

假设我有两门课:

public class Parent {
   public Child Child { get; set; }
}

public class Child {
   public string Name { get; set; }
}
我想写一个函数,通过包含子字符串的孩子的名字过滤父母

public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
   return parents.Where(parent => parent.Child.Name.Contains(word));
}
public IQueryable parentschildname匹配(IQueryable parents,字符串字)
{
返回parents.Where(parent=>parent.Child.Name.Contains(word));
}
如果我想提取这个表达式,这样我就可以在别处重用子contains check

public Expression<Func<Child, bool> ChildNameMatches(string word)
{
   return child => child.Name.Contains(word));
}
公共表达式child.Name.Contains(word)); } 然后我如何在我的中使用它,以便我可以重写ParentsChildNameMatches

public IQueryable<Parent> ParentsChildNameMatches(IQueryable<Parent> parents, string word)
{
   return parents.Where( // how to leverage ChildNameMatches?
}
public IQueryable parentschildname匹配(IQueryable parents,字符串字)
{
返回parents.Where(//如何利用ChildNameMatches?
}

因此,给定一个
表达式
,并且您可以通过
父类
中的
子类
属性创建一个从
父类
子类
的表达式,您希望获得一个
表达式

您可以使用手动执行此操作,也可以使用以下第三方库:

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);
}
public IQueryable parentschildname匹配(IQueryable parents,字符串字)
{
var childExpression=ChildNameMatches(word);
Expression=p=>childExpression.Invoke(p.Child);
expression=expression.Expand();
返回父母。其中(表达式);
}
LinqKit提供了
Invoke
方法,允许您将表达式组合在一起。它还提供了
Expand
方法,用于展平结果表达式

您可以在此处阅读更多关于此的信息:


更新:以前的代码不起作用。已修复。

因此,给定一个
表达式
,并且您可以通过
父类
中的
子类
属性创建一个从
父类
子类的表达式,您希望获得一个
表达式

您可以使用手动执行此操作,也可以使用以下第三方库:

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);
}
public IQueryable parentschildname匹配(IQueryable parents,字符串字)
{
var childExpression=ChildNameMatches(word);
Expression=p=>childExpression.Invoke(p.Child);
expression=expression.Expand();
返回父母。其中(表达式);
}
LinqKit提供了
Invoke
方法,允许您将表达式组合在一起。它还提供了
Expand
方法,用于展平结果表达式

您可以在此处阅读更多关于此的信息:


更新:以前的代码不起作用。已修复。

您可以将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);
}
公共静态IQueryable parentschildname匹配(IQueryable parents,字符串字)
{
var childPredicate=ChildNameMatches(word);
var parent=表达式参数(typeof(parent),“parent”);
var parentPredicate=Expression.Lambda(
表达式.调用(
儿童谓词,
表达式.属性(父,“子”),
父母);
返回parents.Where(parentPredicate);
}

此代码将创建一个新表达式
parent=>parent.Child
,并将其用作
childPredicate
的参数。您可以将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);
}
公共静态IQueryable parentschildname匹配(IQueryable parents,字符串字)
{
var childPredicate=ChildNameMatches(word);
var parent=表达式参数(typeof(parent),“parent”);
var parentPredicate=Expression.Lambda(
表达式.调用(
儿童谓词,
表达式.属性(父,“子”),
父母);
返回parents.Where(parentPredicate);
}

此代码将创建一个新表达式
parent=>parent.Child
并将其用作
childPredicate

的参数实际上,您的
ChildNameMatches
是否应该接受
parent
,而不是
Child
,并将其作为
返回parent=>parent.Child…
?好的,我的目标是,然后可以重用ChildNameMatches表达式可以单独为子类匹配,也可以在存在具有子属性的其他父类时匹配。如果在
子类中定义了该特定方法
ChildNameMatches
,则可以添加另一个方法,该方法具有我为
父类
建议的签名,否则将无法执行在
.Where()中直接使用它
调用。实际上,您的
ChildNameMatches
是否应该接受
父类
,而不是
子类
,并且是
返回父类=>Parent.Child….
?好的,我的目标是,我可以自己为任何一个子类重用ChildNameMatches表达式,或者当有其他具有子类的父类时属性。如果在
Child
类中定义了特定的方法
ChildNameMatches
,那么您可以使用我为
父类
建议的签名添加另一个方法,否则您将无法在该
类中直接使用它。其中()
invocation。谢谢你,更新后,这对我很有用。出于好奇,你什么时候需要额外使用linqkit.entityframework?我真的不知道。也许你可以在库的项目站点上找到这些信息。谢谢你,更新后,这对我很有用。出于好奇,你什么时候需要额外使用linqkit.entityframework?我真的不知道。也许你可以在图书馆的项目网站上找到这些信息。