Laden...

Linq Expressions verknüpfen

Erstellt von ByteDevil vor 4 Jahren Letzter Beitrag vor 4 Jahren 4.315 Views
ByteDevil Themenstarter:in
132 Beiträge seit 2013
vor 4 Jahren
Linq Expressions verknüpfen

Beschreibung:

Hier sind zwei Erweiterungsmethoden für System.Linq.Expressions.Expression, welche es ermöglichen zwei Linq-Expressions logisch zu "verodern" bzw. zu "verunden". Der Code ist nicht von mir, nur leicht von mir angepasst. Weiß leider nicht mehr genau woher ich den habe, musste aber lange nach sowas suchen. Verwende es um eine Datenbankabfrage, unter Angabe eines Query Strings aus der URL eines Webservices, zu generieren.


public static class ExpressionExtensions
{
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
    {
        var parameter = Expression.Parameter(typeof(T));

        var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
        var left = leftVisitor.Visit(expr1.Body);

        var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
        var right = rightVisitor.Visit(expr2.Body);

        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(left, right), parameter);
    }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
    {
        var parameter = Expression.Parameter(typeof(T));

        var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
        var left = leftVisitor.Visit(expr1.Body);

        var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
        var right = rightVisitor.Visit(expr2.Body);

        return Expression.Lambda<Func<T, bool>>(
            Expression.OrElse(left, right), parameter);
    }

    private class ReplaceExpressionVisitor : ExpressionVisitor
    {
        private readonly Expression _oldValue;
        private readonly Expression _newValue;

        public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
        {
            _oldValue = oldValue;
            _newValue = newValue;
        }

        public override Expression Visit(Expression node)
        {
            if (node == _oldValue)
                return _newValue;
            return base.Visit(node);
        }
    }
}

Verwendung:


List<Expression<Func<string, bool>>> expressions = new List<Expression<Func<string, bool>>>();
expressions.Add(x => x.ToLower().Contains("foo") || x.ToLower().Contains("bar"));
expressions.Add(x => !x.ToLower().Contains("not this"));

var combinedExpression = expressions.Aggregate((x, y) => x.And(y));

Schlagwörter: Linq, Verknüpfen, Linq OR, Linq AND