在IQueryable上应用内部表达式筛选器



假设我有以下对象:

public class Source { public string Name; }
public class Target { public string Name; }
public class Result 
{ 
public Source SourceObj; 
public Target TargetObj; 
} 

现在,从某个地方获得IQueryable<Result>,我想为它准备表达式过滤器,只需要将Target过滤器作为表达式:Expression<Func<Target, bool>> filter。过滤器方法签名如下所示:

public Expression<Func<Result, bool>> Filter(IQueryable<Result> collection, Expression<Func<Target, bool>> targetFilter)
{ 
in result expression: "in given collection select items where their property TargetObj satisfies targetFilter"
}

如有任何建议,我们将不胜感激。感谢

我不确定我是否正确理解了你的目标,但我认为这可能是你想要的。

使用linqSelect,可以映射源集合中的元素。因此,我们将结果映射到目标,然后应用目标过滤器。

public IQueryable<Target> GetFilteredTargets(IQueryable<Result> collection, Expression<Func<Target, bool>> targetFilter)
{
return collection.Select(result => result.Target).Where(targetFilter);
}

如果您真的想要一个表达式作为Filter方法的返回,则不需要IQueryable<Result> collection

public Expression<Func<Result, bool>> Filter(Expression<Func<Target, bool>> targetFilter)
{
Func<Target, bool> func = targetFilter.Compile();
Expression<Func<Result, bool>> resultExpression = r => func(r.TargetObj);
return resultExpression;
}

用法:

var results = new List<Result>()
{
new Result() { TargetObj = new Target() { Name = "A" }},
new Result() { TargetObj = new Target() { Name = "B" }},
new Result() { TargetObj = new Target() { Name = "C" }},
};
var expression = Filter(r => r.Name == "B");
var func = expression.Compile();
var filteredResults = results.Where(r => func(r));

这里的样本过滤结果将返回带有B的目标。根据我对您目标的理解,直接使用Linq-Where对我来说更有意义。

编辑:既然你在问题中添加了一个新的因素,那么如何将目标过滤器添加到基本过滤器中。

public Expression<Func<Result, bool>> Filter(Expression<Func<Result, bool>> baseFilter, Expression<Func<Target, bool>> targetFilter)
{
Func<Result, bool> baseFunc = baseFilter.Compile();
Func<Target, bool> targetFunc = targetFilter.Compile();
Expression<Func<Result, bool>> resultExpression = r => baseFunc(r) && targetFunc(r.TargetObj);
return resultExpression;
}

最新更新