C# 包含多个排序参数的动态Linq自然排序

C# 包含多个排序参数的动态Linq自然排序,c#,linq,sorting,dynamic-linq,C#,Linq,Sorting,Dynamic Linq,正如标题所描述的,是否有任何方法可以使用动态Linq实现自然排序,包括支持多个排序参数 最好我想做这样的事情(使用定制的IComparer): List invoices=Provider.GetInvoices(); 发票=发票 .AsQueryable() .OrderBy(“排序参数1 ASC,排序参数2 ASC”,新的NaturalSort()) .ToList(); 看起来您想要这个: invoices = invoices .OrderBy(invoice => inv

正如标题所描述的,是否有任何方法可以使用动态Linq实现自然排序,包括支持多个排序参数

最好我想做这样的事情(使用定制的IComparer):

List invoices=Provider.GetInvoices();
发票=发票
.AsQueryable()
.OrderBy(“排序参数1 ASC,排序参数2 ASC”,新的NaturalSort())
.ToList();

看起来您想要这个:

invoices = invoices
    .OrderBy(invoice => invoice.SortingParameter1, new NaturalSort())
    .ThenBy(invoice => invoice.SortingParameter2, new NaturalSort())
    .ToList();
基本上,您希望对第一个排序参数使用
OrderBy
OrderByDescending
,然后对其余参数使用
ThenBy
ThenByDescending

(注意这里不需要
AsQueryable
,因为
List
扩展了
IEnumerable

DynamicLink没有将
IComparer
作为参数的方法
OrderBy
,所以您不能传递自定义比较器,但您可以这样修改源代码

public static IQueryable<T> OrderBy<T,ComparerType>(this IQueryable<T> source, IComparer<ComparerType> comparer, string ordering, params object[] values)
{
    return (IQueryable<T>)OrderBy((IQueryable)source, comparer, ordering, values);
}

public static IQueryable OrderBy<ComparerType>(this IQueryable source, IComparer<ComparerType> comparer, string ordering, params object[] values)
{
    if (source == null) throw new ArgumentNullException("source");
    if (ordering == null) throw new ArgumentNullException("ordering");
    ParameterExpression[] parameters = new ParameterExpression[] {
        Expression.Parameter(source.ElementType, "") };
    ExpressionParser parser = new ExpressionParser(parameters, ordering, values);
    IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();
    Expression queryExpr = source.Expression;
    string methodAsc = "OrderBy";
    string methodDesc = "OrderByDescending";
    foreach (DynamicOrdering o in orderings)
    {
        queryExpr = Expression.Call(
            typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
            new Type[] { source.ElementType, o.Selector.Type },
            queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)), Expression.Constant(comparer));
            methodAsc = "ThenBy";
            methodDesc = "ThenByDescending";
        }
    return source.Provider.CreateQuery(queryExpr);
}
List<Invoice> invoices = Provider.GetInvoices();

invoices = invoices.AsQueryable()
                   .OrderBy(new NaturalSort(), "SortingParameter1 ASC, SortingParamaeter 2 ASC")
                   .ToList();
公共静态IQueryable OrderBy(此IQueryable源、IComparer比较器、字符串排序、参数对象[]值)
{
返回(IQueryable)OrderBy((IQueryable)源、比较器、排序、值);
}
公共静态IQueryable OrderBy(此IQueryable源、IComparer比较器、字符串排序、参数对象[]值)
{
如果(source==null)抛出新的ArgumentNullException(“source”);
if(ordering==null)抛出新的ArgumentNullException(“ordering”);
ParameterExpression[]参数=新的ParameterExpression[]{
Expression.Parameter(source.ElementType,“”)};
ExpressionParser=新的ExpressionParser(参数、顺序、值);
IEnumerable orderings=parser.ParseOrdering();
表达式queryExpr=source.Expression;
string methodAsc=“OrderBy”;
string methodDesc=“OrderByDescending”;
foreach(订单中的动态记录)
{
queryExpr=Expression.Call(
typeof(可查询),o.升序?methodAsc:methodDesc,
新类型[]{source.ElementType,o.Selector.Type},
queryExpr,Expression.Quote(Expression.Lambda(o.Selector,parameters)),Expression.Constant(comparer));
methodAsc=“ThenBy”;
methodDesc=“然后按降序”;
}
返回source.Provider.CreateQuery(queryExpr);
}
像这样使用它

public static IQueryable<T> OrderBy<T,ComparerType>(this IQueryable<T> source, IComparer<ComparerType> comparer, string ordering, params object[] values)
{
    return (IQueryable<T>)OrderBy((IQueryable)source, comparer, ordering, values);
}

public static IQueryable OrderBy<ComparerType>(this IQueryable source, IComparer<ComparerType> comparer, string ordering, params object[] values)
{
    if (source == null) throw new ArgumentNullException("source");
    if (ordering == null) throw new ArgumentNullException("ordering");
    ParameterExpression[] parameters = new ParameterExpression[] {
        Expression.Parameter(source.ElementType, "") };
    ExpressionParser parser = new ExpressionParser(parameters, ordering, values);
    IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();
    Expression queryExpr = source.Expression;
    string methodAsc = "OrderBy";
    string methodDesc = "OrderByDescending";
    foreach (DynamicOrdering o in orderings)
    {
        queryExpr = Expression.Call(
            typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
            new Type[] { source.ElementType, o.Selector.Type },
            queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)), Expression.Constant(comparer));
            methodAsc = "ThenBy";
            methodDesc = "ThenByDescending";
        }
    return source.Provider.CreateQuery(queryExpr);
}
List<Invoice> invoices = Provider.GetInvoices();

invoices = invoices.AsQueryable()
                   .OrderBy(new NaturalSort(), "SortingParameter1 ASC, SortingParamaeter 2 ASC")
                   .ToList();
List invoices=Provider.GetInvoices();
发票=发票。AsQueryable()
.OrderBy(新的NaturalSort(),“排序参数1 ASC,排序参数2 ASC”)
.ToList();
其中
NaturalSort
应实现
IComparer
关于实现Narual排序,您可以看到


注意:但我不确定这是否适用于其他提供商,如db

不,对不起,这不是我想要的。我想使用sortingparameters作为字符串,因为参数在运行时之前是未知的。Dynamic Linq实现了这一点,但是我无法找到一种方法来使用自定义IComparer实现“自然排序”/“自然数字排序”。DynamicLinq没有将IComparer作为参数的方法
OrderBy
,因此您无法传递自定义比较器,但您可以修改源代码want@Philip,我想再次提请大家注意一个事实,我不确定它是否能与数据库一起工作。这没问题,因为我只使用它对ILists中的对象进行排序。不过有件奇怪的事。它在我的开发机器上运行得很好,但是当我发布它时,我得到了以下异常:“没有泛型方法'OrderBy'on type'System.Linq.Queryable'与提供的类型参数和参数兼容。如果该方法是非泛型的,则不应提供类型参数。”。所有的dll都是最新的。@Philip,你能用
dynamicLink在dll中看到这个方法吗?在哪里添加此代码?在源代码中重新编译它?或者其他地方?是的,我将您的代码添加到System.Linq.Dynamic命名空间中的DynamicQueryable类中,因此您的方法与所有其他动态Linq方法都在其中。非常奇怪..@Philip,请尝试在发布后将开发人员计算机上的dll与dll进行比较,也可能在发布后您对不同的dll有参考