2014-10-30 36 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