2014-10-30 51 views
5

我有一個列表object s。我如何使用屬性名稱來訂購這個列表?按屬性名稱(字符串值)排序列表?

string orderbyField = "Code"; 
List<object> l = FillList(); 
l = l.OrderBy(o => orderbyField); 

我可以爲這個問題擴展嗎?

+0

你能提供FillList – 2014-10-30 06:23:32

+1

的完整代碼段值得關注的是你有**對象名單**沒有具體的類,所以你怎麼能保證列表中的所有對象都具有名爲「代碼」的屬性..更好地創建特定類型的列表..或具有多個類型使用接口類型列表 – 2014-10-30 06:24:52

+0

我不能擁有特定的類型。 FillList返回一個LINQ實體對象。 s.t像dc.Employer。我使用這個列表作爲MVC.NET中自定義網格的數據源。 – 2014-10-30 06:31:10

回答

14

如果沒有提供屬性的名稱作爲一個字符串,它使用dynamic很簡單:

List<object> l = FillList(); 
l = l.OrderBy(o => ((dynamic)o).Id); 

如果屬性名稱必須是一個字符串,那麼它變得有點複雜,但可以使用反射來完成(雖然效率不高):

l = l.OrderBy(o => o.GetType() 
        .GetProperty("Code") 
        .GetValue(o, null)); 

您還應該考慮添加一些錯誤處理,例如如果該屬性不存在。另外,如果列表中的所有元素都具有相同的運行時類型,那麼使用表達式樹並重新使用它(而不是直接使用反射)來編譯getter函數會更有效率。

public static Func<object, object> CreateGetter(Type runtimeType, string propertyName) 
{ 
    var propertyInfo = runtimeType.GetProperty(propertyName); 

    // create a parameter (object obj) 
    var obj = Expression.Parameter(typeof(object), "obj"); 

    // cast obj to runtimeType 
    var objT = Expression.TypeAs(obj, runtimeType); 

    // property accessor 
    var property = Expression.Property(objT, propertyInfo); 

    var convert = Expression.TypeAs(property, typeof(object)); 
    return (Func<object, object>)Expression.Lambda(convert, obj).Compile(); 
} 

,並用它喜歡:

var codeGetter = CreateGetter(l[0].GetType(), "Code"); // using the 1st element as an example 
l = l.OrderBy(o => codeGetter(o)); 
+0

非常感謝Eren,它工作。 – 2014-10-30 07:36:07