2010-11-02 8 views
1

Salut laisse dire que j'ai un chemin de propriété qui ressemble à ceciConstruire une expression Lambda d'une PropertyPath

On peut dire que j'ai un article qui a une Vat et Vat a une valeur. Maintenant, je veux utiliser LINQ pour trier une liste en utilisant cette voie de la propriété Comment puis-je construire cette expression lambda quand j'ai « Vat.Value » dans une chaîne et je veux le résultat suivant

list.Order(x => x.Vat.Value) 

Je ne vais pas toujours connaître les types de TVA et de valeur, parfois son seul x.Nom, je suis dehors.

Répondre

0

Je ne suis pas sûr de comprendre totalement la question, mais quelque chose comme ça ressemble à ce que vous voulez. Notez que je refactoriserais probablement le lambda en une méthode d'aide en production pour plus de clarté. Notez également que l'utilisation de ce type de réflexion peut être un facteur de performance important en fonction de la taille de votre collection.

[Test] 
public void OrderByUsingReflection() 
{ 
    var values = new[] 
    { 
     new { Vat = new { Value = "two"}}, 
     new { Vat = new {Value = "one"}}, 
    }; 

    var result = values.OrderBy(x => 
    { 
     var vat = x.GetType().GetProperty("Vat").GetValue(x, null); 
     return vat.GetType().GetProperty("Value").GetValue(vat, null); 
    }); 

    Assert.AreEqual(result.ToList()[0], values[1]); 
    Assert.AreEqual(result.ToList()[1], values[0]); 
} 
+0

Je pense que celui que j'ai posté maintenant est plus performant et plus facile à utiliser. – NPehrsson

1

Je l'ai fixé avec une méthode d'extension. L'approche d'utiliser un PropertyPath est maintenant par exemple

var orderedArticles = articles.OrderBy("Vat.Value"); 

au lieu de

var orderedArticles = articles.OrderBy(x => x.Vat.Value) 

Méthodes d'extension:

private static Func<T, TReturnType> GetLambda<T, TReturnType>(IEnumerable<string> propertyNames) 
{ 
    var rootParameterExression = Expression.Parameter(typeof(T)); 

    Expression expression = rootParameterExression; 
    foreach (var propertyName in propertyNames) 
    { 
     expression = Expression.Property(expression, propertyName); 
    } 
    return Expression.Lambda<Func<T, TReturnType>>(expression, rootParameterExression).Compile(); 
} 

public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> queryable, string propertyPath) 
{ 
    var propertyPathList = propertyPath.Split(Convert.ToChar(".")); 
    Type propertyType = typeof(T); 
    foreach (var propertyName in propertyPathList) 
    { 
     propertyType = propertyType.GetProperty(propertyName).PropertyType; 
    } 

    if(propertyType == typeof(decimal)) 
    { 
     var lambda = GetLambda<T, Decimal>(propertyPathList); 
     return queryable.OrderBy(lambda); 
    } 
    var lamda = GetLambda<T, object>(propertyPathList); 
    return queryable.OrderBy(lamda); 
} 
Questions connexes