2010-11-02 34 views
1

嗨可以說我有一個屬性路徑看起來像這樣構建從一個的PropertyPath Lambda表達式

我們可以說,我有一個具有還原的文章和增值稅有一個值。 現在我想使用Linq使用屬性路徑 我怎樣才能建立一個lambda表達式時,我在字符串中有「Vat.Value」排序名單,我想下面的結果

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

我不會總是知道增值稅和價值的類型,有時只有我出去的x.Name。

回答

0

我不確定我完全理解這個問題,但是像這樣的東西看起來像你想要的。請注意,爲了清楚起見,我可能會將lambda重構爲輔助方法。還要注意,使用這種反射可能會導致性能顯着下降,具體取決於您的收藏有多大。

[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

我認爲我現在發佈的那個更高效,更易於使用。 – NPehrsson 2010-11-02 20:22:59

1

我用擴展方法修復了它。該方法使用的PropertyPath現在例如

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

,而不是

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

擴展方法:

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); 
}