DEV Community

nazmoonnoor
nazmoonnoor

Posted on

Using LinqKit PredicateBuilder to dynamically build filter conditions

In C#, predicates are delegate which forms the method that defines a list of criteria and verify if the object meets those criteria.

Many times building a predicate dynamically solves many headaches to filter out the models or data. PredicateBuilder from LinqKit comes to rescue here.

PredicateBuilder extension method is as follows.

using System;
using System.Linq;
using System.Linq.Expressions;

namespace Core
{
    /// <summary>
    /// PredicateBuilder is a extension class from LINKit library
    /// See http://www.albahari.com/expressions for information and examples.
    /// </summary>
    public static class PredicateBuilder
    {
        public static Expression<Func<T, bool>> True<T>() { return f => true; }
        public static Expression<Func<T, bool>> False<T>() { return f => false; }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                            Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                             Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Here is an example use,

Expression<Func<BillingAccountReport, bool>> SearchBillingAccount(BillingAccountReportParams queryParams)
{
    var predicate = PredicateBuilder.True<BillingAccountReport>();

    if (queryParams == null)
        return predicate;

    if (queryParams.StartDate != null)
    {
        predicate = predicate.And(p => p.SubscriptionCreated >= queryParams.StartDate);
    }
    if (queryParams.EndDate != null)
    {
        predicate = predicate.And(p => p.SubscriptionCreated >= queryParams.EndDate);
    }
    if (queryParams.BillingAccountIds != null && queryParams.BillingAccountIds.Count() > 0)
    {
        foreach (string id in queryParams.BillingAccountIds)
            predicate = predicate.Or(p => p.Id.Contains(id));
    }

    return predicate;
}
Enter fullscreen mode Exit fullscreen mode

Happy coding.

Top comments (0)