问题
I'm writing a custom Entity Framework filter. I have a list of IDs, and a user-supplied expression.
protected IEnumerable<TColumn> FilterIds;
protected Expression<Func<T, IEnumerable<TColumn>, bool>> Filter;
Now my question is how do I apply the Filter
expression to a Where()
clause?
public virtual IQueryable<T> ApplyFilter(IQueryable<T> query)
{
if (FilterMode == FilterModeMatchAny && HasFilterIds)
{
// Whoops! Can't do this!
return query.Where(x => Filter(x, FilterIds));
}
return query;
回答1:
Using the Combine
method from this post does pretty much everything you need. From there you just need to turn the literal value into an expression that computes it (or I guess alter the Combine
method from that answer so that the intermediate value isn't computed from a lambda but rather is just any expression), and then call the function.
protected IEnumerable<TColumn> FilterIds;
protected Expression<Func<T, IEnumerable<TColumn>> FilterIdsExpression => _ => FilterIds;
protected Expression<Func<T, IEnumerable<TColumn>, bool>> Filter;
public virtual IQueryable<T> ApplyFilter(IQueryable<T> query)
{
if (FilterMode == FilterModeMatchAny && HasFilterIds)
{
return query.Where(FilterIdsExpression.Combine(Filter));
}
return query;
}
回答2:
You can create a new expression to invoke the Filter
using the FilterIds
and use Expand
from LinqKit
Edit Thanks to @Servy's comment. Now I expand only the internal expression instead of entire query.
...
protected IEnumerable<TColumn> FilterIds;
protected Expression<Func<T, IEnumerable<TColumn>, bool>> Filter;
public virtual IQueryable<T> ApplyFilter(IQueryable<T> query)
{
if (FilterMode == FilterModeMatchAny && HasFilterIds)
{
Expression<Func<T, bool>> expression = x => Filter.Invoke(x, FilterIds);
return query.Where(expression.Expand());
}
return query;
}
...
来源:https://stackoverflow.com/questions/62879661/applying-an-expression-to-a-linq-where-clause