将IComparer参数传递给自定义LINQ OrderBy扩展方法
本文关键字:OrderBy 扩展 方法 LINQ 自定义 IComparer 参数传递 | 更新日期: 2023-09-27 18:24:13
经过大量的谷歌搜索和尝试,但没有找到/得到想要的结果,我决定发布这个问题。
我有一个自定义的OrderBy
扩展方法,现在在执行OrderBy
操作时,我想传递一个AlphanumComparator
,如下所示:
return divergences.OrderBy(sort, new AlphanumComparator());
以下是扩展方法:
public static IQueryable<T> OrderBy<T>(this IQueryable<T> collection,
GridSortOptions sortOptions, AlphanumComparator comparer = null)
{
if (string.IsNullOrEmpty(sortOptions.Column))
{
return collection;
}
Type collectionType = typeof(T);
ParameterExpression parameterExpression = Expression.Parameter(collectionType, "p");
Expression seedExpression = parameterExpression;
Expression aggregateExpression = sortOptions.Column.Split('.').Aggregate(seedExpression, Expression.Property);
MemberExpression memberExpression = aggregateExpression as MemberExpression;
if (memberExpression == null)
{
throw new NullReferenceException(string.Format("Unable to cast Member Expression for given path: {0}.", sortOptions.Column));
}
LambdaExpression orderByExp = Expression.Lambda(memberExpression, parameterExpression);
const string orderBy = "OrderBy";
const string orderByDesc = "OrderByDescending";
Type childPropertyType = ((PropertyInfo)(memberExpression.Member)).PropertyType;
string methodToInvoke = sortOptions.Direction == MvcContrib.Sorting.SortDirection.Ascending ? orderBy : orderByDesc;
MethodCallExpression orderByCall;
orderByCall = Expression.Call(typeof(Queryable), methodToInvoke, new[] { collectionType, childPropertyType }, collection.Expression, Expression.Quote(orderByExp));
if(comparer != null)
{
// How can I pass the comparator to the OrderBy MethodCallExpression?
// Using the standard LINQ OrderBy, we can do this:
// elements.OrderBy(e => e.Index, new AlphanumComparator())
}
return collection.Provider.CreateQuery<T>(orderByCall);
}
请参阅代码中我认为应该通过IComparer
的注释。。。我该如何处理?
我不得不采取不同的方法。
我试图创建一个用于MvcContrib网格的通用OrderBy
,但将IComparer
传递给自定义OrderBy
表达式并没有像我想象的那样起作用。
所以我创建了这个助手,它接收像Element1.Standard.Chapter.Manual.Name
这样的点符号字符串,然后返回一个Expression<Func<T, string>>
:
public static Func<T, string> CreateSelectorExpression<T>(string propertyName) where T : class
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(T));
Expression aggregateExpression = propertyName.Split('.').
Aggregate(parameterExpression as Expression, Expression.Property) as MemberExpression;
LambdaExpression exp = Expression.Lambda(aggregateExpression, parameterExpression);
return (Func<T, string>)exp.Compile();
}
这个类型为T的表达式(在本例中为Divergence
对象类型)然后可以传递(参见func.Invoke
)给标准LINQ OrderBy
运算符,在那里我还可以传递自定义IComparer
AlphanumComparator
,如下所示:
if (sort.Column.Contains("Index"))
{
var func = Helpers.ExtensionMethods.CreateSelectorExpression<Divergence>(sort.Column);
if (sort.Direction == SortDirection.Ascending)
{
return divergences.OrderBy(func, new AlphanumComparator());
}
else
{
return divergences.OrderByDescending(func, new AlphanumComparator());
}
}
这涉及到更多的工作,但以我希望的通用方式解决了问题。