2016-02-25 2 views
1

Toutes les excuses si cela est couvert dans d'autres réponses. J'ai cherché toute la nuit et je suis passé par une centaine d'autres solutions, mais je n'arrivais pas à assembler les pièces du puzzle. J'ai expérimenté avec LinqPad, PredicateBuilder, ExpressionVisitors, etc. mais je me gratte toujours la tête.Génération d'une expression <Func <TEntity, bool >> pour l'expression multiniveau

Je suis en train de mettre en œuvre quelque chose un peu plus compliqué que cela, mais ce code montre la question:

public Expression<Func<TEntity, bool>> GeneratorEqualityTest<TProperty>(Expression<Func<TEntity, TProperty>> accessor, int expectedValue) { 
    // Help 
    var argument = Expression.Parameter(typeof(TEntity)); 
    var accessorArgument = Expression.Property(argument, accessor.ToPropertyName()); 
    // Help 

    Predicate = Expression.Lambda<Func<TEntity, bool>>(Expression.Equal(accessorArgument, Expression.Constant(expectedValue)), argument); 
} 

Cela fonctionne bien quand est quelque chose comme accesseur ceci: x => x.Value

Mais pas avec x => x.Complex.Value ou x => x.Complex.MoreComplex.Value J'essaie d'analyser des expressions à partir de chaînes telles que> = 5 ou (5 ... 10) et de générer des expressions que je peux insérer dans la clause Where d'une requête LINQ-EF (et g et traduit en T-SQL). Cela fonctionne bien pour le cas à un seul niveau, mais je ne peux pas comprendre comment marcher l'expression.

Dans EF, x.Complex.MoreComplex.Value correspond aux jointures SQL. Les points de bonus s'il est possible de convertir l'accesseur en quelque chose que je peux passer dans une Include() déclaration

Je mets un exemple de projet sur Github: https://github.com/scottt732/ExpressionHelp

+0

Ne devrait-il pas être 'TProperty expectedValue' au lieu de' int'? –

Répondre

2

Puisque vous recevez l'accesseur de valeur finale, tout ce que vous en avez besoin pour appliquer la fonction de comparaison (par exemple construire le corps du prédicat):

public Expression<Func<TEntity, bool>> GeneratorEqualityTest<TProperty>(Expression<Func<TEntity, TProperty>> accessor, TProperty expectedValue) 
{ 
    var body = Expression.Equal(accessor.Body, Expression.Constant(expectedValue)); 
    var predicate = Expression.Lambda<Func<TEntity, bool>>(body, accessor.Parameters); 
    return predicate; 
} 

procédé supplémentaire:

static class ExpressionUtils 
{ 
    public static IEnumerable<Expression<Func<TEntity, object>>> Includes<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> accessor) 
    { 
     var root = accessor.Parameters[0]; 
     for (var node = accessor.Body as MemberExpression; node != null && node.Expression != root; node = node.Expression as MemberExpression) 
      yield return Expression.Lambda<Func<TEntity, object>>(node.Expression, root); 
    } 
} 
+0

Merci! C'est exactement ce dont j'avais besoin. – scottt732

+0

Une idée de ce qu'il faudrait pour convertir l'expression > 'x => x.Complex.MoreComplex.Value' en une expression > []' x => x. Complex.MoreComplex'? Cette dernière expression serait utilisable en tant qu'instruction Include pour optimiser la requête que je génère. – scottt732

+0

Bien sûr. Ajouté à la réponse. –