将IComparer参数传递给自定义LINQ OrderBy扩展方法 [英] Passing an IComparer parameter to custom LINQ OrderBy extension method

查看:225
本文介绍了将IComparer参数传递给自定义LINQ OrderBy扩展方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过大量的Google搜索并尝试了一些事情却没有找到/获得所需的结果后,我决定发布此问题.

After a good dose of Googling and trying some things and not finding/getting the desired result I decided to post this question.

我有一个自定义的OrderBy扩展方法,现在执行OrderBy操作时,我想传递一个 AlphanumComparator 像这样:

I have a custom made OrderBy extension method and now when performing the OrderBy operation I'd like to pass an AlphanumComparator like this:

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 ...我该如何处理?

See the comment in the code where I think I should pass the IComparer... how could I approach this?

推荐答案

我不得不采取不同的方法.

I had to approach this differently.

我试图创建一个通用的OrderBy以与 MvcContrib网格一起使用,但将 IComparer 传递给该自定义OrderBy表达式无法正常工作.

I was trying to create a generic OrderBy to be used with MvcContrib Grid, but passing the IComparer to that custom OrderBy expression did not work as I imagined it would work.

因此,我创建了这个帮助程序,该帮助程序以点表示法(如Element1.Standard.Chapter.Manual.Name)接收字符串,然后返回Expression<Func<T, string>>:

So I created this helper that receives a string in dot notation like Element1.Standard.Chapter.Manual.Name and then returns an 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这个:

This expression typed to T (in this case Divergence object type) can then be passed (see func.Invoke) to the standard LINQ OrderBy operator where I can also pass the custom IComparer AlphanumComparator like this:

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());
    }
}

这涉及更多的工作,但是以我希望的方式通用地解决了这个问题.

This involved a little bit more work but solved the problem in a generic fashion the way I wanted it to be.

这篇关于将IComparer参数传递给自定义LINQ OrderBy扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆