假设我有以下对象:
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;
}