Search code examples
c#lambdaexpression-treesspecification-pattern

Exclude null or empty string value from lambda expression


In my app in GetAll function I have a parameter which is called (CustomerModel). I use it to do some filtering over the query and I used specification pattern to avoid using if-else :

    public async Task<List<CustomerModel>> GetAllAsync(CustomerModel customer, Order order = Order.Ascending, int pageIndex = 1, int pageSize = int.MaxValue)
    {
        var skip = (pageIndex - 1) * pageSize;

        var filter = new CustomerNameSpecification(customer)
            .And(new CustomerNoSpecification(customer))
            .And(new CustomerCompanySpecification(customer))
            .And(new CustomerPhoneSpecification(customer))
            .And(new CustomerEmailSpecification(customer))
            .And(new CustomerAddressSpecification(customer))
            .Take(pageSize)
            .Skip(skip);

        var orderSpecification = new CustomerOrderSpecification(order);

        return await _customerRepository.GetAllAsync(filter, orderSpecification);
    }

And for instance one of the specification objects (CustomerNameSpecification) :

public class CustomerNameSpecification : Specification<Customer>
{
    public CustomerModel Customer { get; set; }

    public CustomerNameSpecification(CustomerModel customerModel)
    {
        Customer = customerModel;
    }

    public override Expression<Func<Customer, bool>> AsExpression()
    {
        return customerFiler =>
            customerFiler.Name.Contains(Customer.Name);
    }
 }

UPDATE

And operation in the specification pattern:

public class AndSpecification<T> : Specification<T> 
    where T : class
{
    private readonly ISpecification<T> _left;
    private readonly ISpecification<T> _right;

    public AndSpecification(ISpecification<T> left, ISpecification<T> right)
    {
        _left = left;
        _right = right;
    }

    public override Expression<Func<T, bool>> AsExpression()
    {
        var leftExpression = _left.AsExpression();
        var rightExpression = _right.AsExpression();

        var parameter = leftExpression.Parameters.Single();
        var body = Expression.AndAlso(leftExpression.Body, SpecificationParameterRebinder.ReplaceParameter(rightExpression.Body, parameter));

        return Expression.Lambda<Func<T, bool>>(body, parameter);
    }
  }
}

And those chains make a lambda expression at the end and repository uses it to filter the query.

This solution works fine when each field of CustomerModel has a value, But it does not work even if one property has a null or empty value.

How can I fix this problem and exclude lambda expression where I have a null or empty string value?


Solution

  • How can I fix this problem and exclude lambda expression where I have a null or empty string value?

    For instance CustomerNameSpecification, to exclude empty value you can use code:

    public override Expression<Func<Customer, bool>> AsExpression()
    {
        return customerFiler => string.IsNullOrWhiteSpace(customerFiler.Name) ||
            customerFiler.Name.Contains(Customer.Name);
    }
    

    If string.IsNullOrWhitespace(customerFiler.Name) returns true then customerFiler.Name.Contains(Customer.Name); will not be evaluated.