简体   繁体   English

如何在规范中生成动态数量的ThenBy子句

[英]How to generate a dynamic number of ThenBy clauses in a Specification

I'm building a Spec Evaluator which must consider multiple possible OrderBy, as in the next example: 我正在构建一个Spec Evaluator,它必须考虑多个可能的OrderBy,如以下示例所示:

if (spec.Order != null)
{
    var count = spec.Order.Count;

    if (count == 1)
    {
        query = query.OrderBy(spec.Order[0]);
    }
    else if (count == 2)
    {
        query = query.OrderBy(spec.Order[0])
            .ThenBy(spec.Order[1]);
    }
    else if (count == 3)
    {
        query = query.OrderBy(spec.Order[0])
            .ThenBy(spec.Order[1])
            .ThenBy(spec.Order[2]);
    }
    // And so on...
}

Query is an IQueryable , spec.Order is a list of clauses: List<Expression<Func<T, object>>> . Query是一个IQueryablespec.Order是以下子句的列表: List<Expression<Func<T, object>>>

I know that I can use an OrderBy with all the clauses passed as string. 我知道我可以将OrderBy与所有作为字符串传递的子句一起使用。 And I guess I can just project all the Order clauses to a new string comma-separated. 而且我想我可以将所有Order子句投影到一个用逗号分隔的新字符串中。 But that solution doesn't seem clean. 但是该解决方案似乎并不干净。

Is there any other way to dynamically generate one new ThenBy for every item of the Order list, above 1? 还有其他方法可以为Order列表中的每个项目(大于1)动态生成一个新的ThenBy吗?

You could use a for loop. 您可以使用for循环。 Basically loop through all of the Order values, use OrderBy for the first one, and ThenBy for subsequent items. 基本上遍历所有Order值,对第一个使用OrderBy ,对随后的项目使用ThenBy Since you've said that you're using IQueryable , I've modified this to use a temporary IOrderedQueryable<T> variable. 由于您已经说过您正在使用IQueryable ,因此我已经对其进行了修改,以使用临时IOrderedQueryable<T>变量。

if (spec.Order != null)
{
    var count = spec.Order.Count;

    IOrderedQueryable<T> orderedQuery = null;
    for (int i = 0; i < count; ++i)
    {
        if (i == 0)
        {
            orderedQuery = query.OrderBy(spec.Order[i]);
        }
        else
        {
            orderedQuery = orderedQuery.ThenBy(spec.Order[i]);
        }
    }
    query = orderedQuery ?? query;
}

You could also approach it like this, although I'm not sure how the performance differs between the two methods, if it does at all: 您也可以这样处理,尽管我不确定这两种方法之间的性能有何不同(如果有的话):

if (spec.Order != null)
{
    var count = spec.Order.Count;

    for (int i = 0; i < count; ++i)
    {
        if (query is IOrderedQueryable<T> orderedQuery)
        {
            query = orderedQuery.ThenBy(spec.Order[i]);
        }
        else
        {
            query = query.OrderBy(spec.Order[i]);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM