Come faccio a creare dynamicmente un predicato Expression <Func >?

Come utilizzerei un albero delle espressioni per creare dynamicmente un predicato simile a qualcosa …

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

In modo che io possa attaccare il predicato in un’espressione lambda così …

 q.Where(myDynamicExpression)... 

Ho solo bisogno di essere indicato nella giusta direzione.

Aggiornamento: Scusate la gente, ho omesso il fatto che voglio che il predicato abbia più condizioni come sopra. Dispiace per la confusione.

Originale

Così:

  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>( body, param); 

aggiornato

re (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>(body, param); 

Utilizzare il generatore di predicati.

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

È piuttosto facile!

Per combinare più predicati con l’operatore && , li unisci insieme due alla volta.

Quindi, se hai una lista di oggetti Expression chiamati predicates , fai questo:

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

Per associare l’espressione Lambda a vicenda: un altro modo è utilizzare il seguente codice. È più flessibile della risposta Schotime nel mio consiglio e funziona perfettamente. Non sono necessarie nughe esterne

Framework 4.0

  // Usage first.Compose(second, Expression.And) public static Expression Compose(this Expression First, Expression Second, Func Merge) { // build parameter map (from parameters of second to parameters of first) Dictionary map = First.Parameters.Select((f, i) => new { f, s = Second.Parameters[i] }).ToDictionary(p => ps, p => pf); // 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(Merge(First.Body, secondBody), First.Parameters); } public static Expression> And(this Expression> First, Expression> Second) { return First.Compose(Second, Expression.And); } public static Expression> Or(this Expression> First, Expression> second) { return First.Compose(second, Expression.Or); } public class ParameterRebinder : ExpressionVisitor { private readonly Dictionary map; public ParameterRebinder(Dictionary map) { this.map = map ?? new Dictionary(); } public static Expression ReplaceParameters(Dictionary 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); } }