LINQ Extensions - C#

Overview

This article provides the code for two extension methods for use when building expressions, commonly used with LINQ. These functions allow you to build Boolean expressions on the fly.


Sample Usage

The CustomerOrder is only used as an example; it can be any class.

Expression<Func<CustomerOrder, bool>> expr = x => false;

if (someCondition)
{
    expr = expr.OrElse(a => a.OrderAmount >= 1000);
}

if (someOtherCondition)
{
    expr = expr.OrElse(a => a.OrderAmount <= 5000);
}

var items = _db.CustomerOrders.Where(expr.AndAlso(a => !a.IsDeleted));

Extension Methods

using System;
using System.Linq.Expressions;

public static class LinqExtensions
{
    /* Adapted from
        * https://stackoverflow.com/questions/29565373/combine-listexpressionfunct-bool-to-an-or-clause-linq
        */
    public static Expression<Func<T, bool>> OrElse<T>(
        this Expression<Func<T, bool>> a,
        Expression<Func<T, bool>> b)
    {
        var bodyB = b.Body.Replace(b.Parameters[0], a.Parameters[0]);

        return Expression.Lambda<Func<T, bool>>(Expression.OrElse(a.Body, bodyB), a.Parameters);
    }


    public static Expression<Func<T, bool>> AndAlso<T>(
        this Expression<Func<T, bool>> a,
        Expression<Func<T, bool>> b)
    {
        var bodyB = b.Body.Replace(b.Parameters[0], a.Parameters[0]);

        return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(a.Body, bodyB), a.Parameters);
    }


    private static Expression Replace(this Expression expression, Expression searchEx, Expression replaceEx)
    {
        return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
    }


    private class ReplaceVisitor : ExpressionVisitor
    {
        private readonly Expression _from, _to;
        public ReplaceVisitor(Expression from, Expression to)
        {
            _from = from;
            _to = to;
        }
        public override Expression Visit(Expression node)
        {
            return node == _from ? _to : base.Visit(node);
        }
    }
}