【发布时间】:2013-07-21 07:37:22
【问题描述】:
我有一组扩展方法,允许在 LINQ OrderBy() 方法中使用魔术字符串。我知道第一个问题是为什么,但它是通用存储库的一部分,并且具有灵活性,因此可以从 UI 发送字符串并直接使用。
如果您传入一个代表您正在查询的主要实体上的属性的魔术字符串,我就可以正常工作,但是我无法使其更通用,以便它可以处理多个级别的深层魔术字符串。例如:
IQueryable<Contact> contacts = GetContacts();
contacts.OrderByProperty("Name"); // works great
// can't figure out how to handle this
contacts.OrderByProperty("ContactType.Name");
这是我目前的代码:
public static class LinqHelpers
{
private static readonly MethodInfo OrderByMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "OrderBy" && method.GetParameters().Length == 2);
private static readonly MethodInfo OrderByDescendingMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "OrderByDescending" && method.GetParameters().Length == 2);
private static readonly MethodInfo ThenByMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "ThenBy" && method.GetParameters().Length == 2);
private static readonly MethodInfo ThenByDescendingMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "ThenByDescending" && method.GetParameters().Length == 2);
public static IOrderedQueryable<TSource> ApplyOrdering<TSource>(IQueryable<TSource> source, string propertyName, MethodInfo orderingMethod)
{
var parameter = Expression.Parameter(typeof(TSource), "x");
var orderByProperty = Expression.Property(parameter, propertyName);
var lambda = Expression.Lambda(orderByProperty, new[] { parameter });
var genericMethod = orderingMethod.MakeGenericMethod(new[] { typeof(TSource), orderByProperty.Type });
return (IOrderedQueryable<TSource>)genericMethod.Invoke(null, new object[] { source, lambda });
}
public static IOrderedQueryable<TSource> OrderByProperty<TSource>(this IQueryable<TSource> source, string propertyName)
{
return ApplyOrdering(source, propertyName, OrderByMethod);
}
public static IOrderedQueryable<TSource> OrderByDescendingProperty<TSource>(this IQueryable<TSource> source, string propertyName)
{
return ApplyOrdering(source, propertyName, OrderByDescendingMethod);
}
public static IOrderedQueryable<TSource> ThenByProperty<TSource>(this IOrderedQueryable<TSource> source, string propertyName)
{
return ApplyOrdering(source, propertyName, ThenByMethod);
}
public static IOrderedQueryable<TSource> ThenByDescendingProperty<TSource>(this IOrderedQueryable<TSource> source, string propertyName)
{
return ApplyOrdering(source, propertyName, ThenByDescendingMethod);
}
}
我很确定我需要在期间拆分propertyName,然后使用这些部分来构建一个更复杂的表达式,其中涉及一个MemberExpression,然后是一个属性,但我很挣扎。任何帮助或指出正确的方向将不胜感激。
【问题讨论】:
-
这适用于子属性,iirc:stackoverflow.com/a/233505/23354 - 请参阅
property.Split('.');和后续循环 -
效果很好。这绝对是答案,所以我赞成评论,因为我无法将其标记为答案。谢谢。
标签: c# linq lambda expression