我有一组CLR对象.该对象的类定义有三个属性:FirstName,LastName,BirthDate.
我有一个字符串,反映了集合应该排序的属性的名称.另外,我有一个排序方向.如何将此排序信息动态应用于我的收藏?请注意,排序可以是多层的,因此我可以按LastName排序,然后按FirstName排序.
目前,我正在尝试以下运气:
var results = myCollection.OrderBy(sortProperty);
Run Code Online (Sandbox Code Playgroud)
但是,我收到的消息是:
...不包含'OrderBy'的定义,并且最好的扩展方法重载......有一些无效的参数.
Jon*_*eet 10
好吧,我在他的评论中与SLaks的争论迫使我想出一个答案:)
我假设你只需要支持LINQ to Objects.这里有一些代码需要大量的验证添加,但确实有效:
// We want the overload which doesn't take an EqualityComparer.
private static MethodInfo OrderByMethod = typeof(Enumerable)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(method => method.Name == "OrderBy"
&& method.GetParameters().Length == 2)
.Single();
public static IOrderedEnumerable<TSource> OrderByProperty<TSource>(
this IEnumerable<TSource> source,
string propertyName)
{
// TODO: Lots of validation :)
PropertyInfo property = typeof(TSource).GetProperty(propertyName);
MethodInfo getter = property.GetGetMethod();
Type propType = property.PropertyType;
Type funcType = typeof(Func<,>).MakeGenericType(typeof(TSource), propType);
Delegate func = Delegate.CreateDelegate(funcType, getter);
MethodInfo constructedMethod = OrderByMethod.MakeGenericMethod(
typeof(TSource), propType);
return (IOrderedEnumerable<TSource>) constructedMethod.Invoke(null,
new object[] { source, func });
}
Run Code Online (Sandbox Code Playgroud)
测试代码:
string[] foo = new string[] { "Jon", "Holly", "Tom", "William", "Robin" };
foreach (string x in foo.OrderByProperty("Length"))
{
Console.WriteLine(x);
}
Run Code Online (Sandbox Code Playgroud)
输出:
Jon
Tom
Holly
Robin
William
Run Code Online (Sandbox Code Playgroud)
它甚至返回一个IOrderedEnumerable<TSource>所以你可以ThenBy正常链接条款:)
您需要构建表达式树并将其传递给OrderBy.
它看起来像这样:
var param = Expression.Parameter(typeof(MyClass));
var expression = Expression.Lambda<Func<MyClass, PropertyType>>(
Expression.Property(param, sortProperty),
param
);
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用Dynamic LINQ,它将允许您的代码按原样工作.
你可以用 Linq 来做到这一点
var results = from c in myCollection
orderby c.SortProperty
select c;
Run Code Online (Sandbox Code Playgroud)