Frage

Wie würde ich einen Ausdrucksbaum verwenden, um ein Prädikat dynamisch zu erzeugen, das so aussieht wie ...

(p.Length== 5) && (p.SomeOtherProperty == "hello") 

Damit ich das Prädikat in einen Lambda -Ausdruck wie so stecken kann ...

q.Where(myDynamicExpression)...

Ich muss nur in die richtige Richtung gezeigt werden.

Aktualisieren: Tut mir leid, Leute, ich habe die Tatsache ausgelassen, dass ich möchte, dass das Prädikat mehrere Bedingungen wie oben hat. Entschuldigung für die Verwirrung.

War es hilfreich?

Lösung

Original

Like SO:

    var param = Expression.Parameter(typeof(string), "p");
    var len = Expression.PropertyOrField(param, "Length");
    var body = Expression.Equal(
        len, Expression.Constant(5));

    var lambda = Expression.Lambda<Func<string, bool>>(
        body, param);

Aktualisiert

betreffend (p.Length== 5) && (p.SomeOtherProperty == "hello"):

var param = Expression.Parameter(typeof(SomeType), "p");
var body = Expression.AndAlso(
       Expression.Equal(
            Expression.PropertyOrField(param, "Length"),
            Expression.Constant(5)
       ),
       Expression.Equal(
            Expression.PropertyOrField(param, "SomeOtherProperty"),
            Expression.Constant("hello")
       ));
var lambda = Expression.Lambda<Func<SomeType, bool>>(body, param);

Andere Tipps

Verwenden Sie den Prädikatbauer.

http://www.albahari.com/nutshell/predicateBuilder.aspx

Es ist ziemlich einfach!

Mehrere Prädikate mit dem zu kombinieren && Bediener, Sie schließen sich ihnen zwei gleichzeitig an.

Wenn Sie also eine Liste von Ausdrucksobjekten haben, die aufgerufen werden predicates, mach das:

Expression combined = predicates.Aggregate((l, r) => Expression.AndAlso(l, r));

Um den Lambda -Ausdruck zu verknüpfen: Eine andere Möglichkeit besteht darin, den folgenden Code zu verwenden. Es ist flexibler als die schotime Antwort in meinem Rat und funktioniert perfekt. Keine externen Nuggets benötigt

Framework 4.0

    // Usage first.Compose(second, Expression.And)
    public static Expression<T> Compose<T>(this Expression<T> First, Expression<T> Second, Func<Expression, Expression, Expression> Merge)
    {
        // build parameter map (from parameters of second to parameters of first)
        Dictionary<ParameterExpression,ParameterExpression> map = First.Parameters.Select((f, i) => new { f, s = Second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);

        // replace parameters in the second lambda expression with parameters from the first
        Expression secondBody = ParameterRebinder.ReplaceParameters(map, Second.Body);

        // apply composition of lambda expression bodies to parameters from the first expression 
        return Expression.Lambda<T>(Merge(First.Body, secondBody), First.Parameters);
    }

    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> First, Expression<Func<T, bool>> Second)
    {
        return First.Compose(Second, Expression.And);
    }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> First, Expression<Func<T, bool>> second)
    {
        return First.Compose(second, Expression.Or);
    }


public class ParameterRebinder : ExpressionVisitor
{
    private readonly Dictionary<ParameterExpression, ParameterExpression> map;

    public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
    {
        this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
    }

    public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
    {
        return new ParameterRebinder(map).Visit(exp);
    }

    protected override Expression VisitParameter(ParameterExpression p)
    {
        ParameterExpression replacement;
        if (map.TryGetValue(p, out replacement))
        {
            p = replacement;
        }
        return base.VisitParameter(p);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top