Expression<Func<object, bool>> as Property

前提是你 提交于 2020-08-09 09:32:40

问题


I am trying to refactor some code for a generic repository, that passes in a filter object that will filter data, as well as page, sort etc.

Each inheriting Filter (Such as CustomerFilter) has the option of defining its own Expression Filter which will get applied by the base class in the repository.

So the customer filter will have properties like this:

public string CustomerId { get; set; }

public override Expression<Func<object, bool>> Predicate => c => ((Customer)c).Id == CustomerId;

Then the repository will run the filter in the repository, a bit like this (it's not generic yet!):

using (var context = new CustomerContext())
{
      return await Filter<Domain.Customer>.ApplyAsync(filter, context.Customers.AsQueryable()).ConfigureAwait(false);
}

This works ok, but I need a way to build the expression in a better way for more complex examples.

For example, the filter may allow to filter the customers on the state, but only if its set.

public string CustomerId { get; set; }

public State? CustomerState { get; set; }

public override Expression<Func<object, bool>> Predicate => c => (((Customer)c).Id == CustomerId) && (((Customer)c).State == CustomerState ?? (Customer)c).State);

This not only becomes a mess, but also there's a lot of unnecessary casting and parenthesis. So what I'd like to do is an expression builder in the getter, that would build the expression in a cleaner way, such as if(State != null) { CustomerState == State; }. But that's where I'm not sure how to proceed, so if anyone can help me out, I'd appreciate it.


回答1:


If you want to combine multiple "Conditions" to apply to Where clause you can use PredicateBuilder from LinqKit library

Here is an example to combine two conditions with "Or" clause

System.Linq.Expressions.Expression<Func<Domain.Question, bool>> codition1 = e => e.CategoryId == 1;
System.Linq.Expressions.Expression<Func<Domain.Question, bool>> condition2 = e => e.CategoryId == 2;
var combinedCondition = LinqKit.PredicateBuilder.Or(codition1, condition2);
//using combined condition in where clause....
queryable = queryable.Where(combinedCondition);

You can use other methods of PredicateBuilder class such as "And" to get the combined condition you want...




回答2:


You can combine expressions with Linq Expressions API:

public Expression<Func<Customer, bool>> BuildExpression()
{
    Expression<Func<Customer, bool>> predicate = c => c.Id == CustomerId;

    if (State != null)
    {
        var parameter = predicate.Parameters.First();
        var newBody = Expression.AndAlso(
            predicate.Body,
            Expression.Equal(
                Expression.PropertyOrField(parameter, nameof(State)),
                Expression.Constant(State)
            ));

        predicate = Expression.Lambda<Func<Customer, bool>>(newBody, parameter);
    }

    return predicate;
}

In code above predicate is a base expression that will be used if State is null. But when State is set we extract expression parameter and add && c.State == State to predicate body



来源:https://stackoverflow.com/questions/56663177/expressionfuncobject-bool-as-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!