Как создать выражение для упорядочения строки по длине

#c# #dynamic #expression-trees #linq-expressions

#c# #динамический #выражение-деревья #linq-выражения

Вопрос:

Я новичок в дереве выражений. Мне нужно упорядочить базу моей коллекции по длине строки, а затем по строке. Я не хочу повторять свой код для каждой сущности. Любой орган знает, как записать его с помощью дерева выражений?

что-то вроде этого:

 public static IQueryable<T> OrderByPropertyOrField<T>(this IQueryable<T> queryable,
  string propertyOrFieldName, bool ascending = true)
{
    var elementType = typeof(T);
    var orderByMethodName = ascending ? "OrderBy" : "OrderByDescending";

    var parameterExpression = Expression.Parameter(elementType);
    var propertyOrFieldExpression = Expression.PropertyOrField(parameterExpression, propertyOrFieldName);
    var selector = Expression.Lambda(propertyOrFieldExpression, parameterExpression);

    var orderByExpression = Expression.Call(typeof(Queryable), orderByMethodName,
        new[] { elementType, propertyOrFieldExpression.Type }, queryable.Expression, selector);

    return queryable.Provider.CreateQuery<T>(orderByExpression);
}
  

Ответ №1:

Если вам нужно упорядочить по строковому значению после упорядочивания по длине строки, вам необходимо вызвать другой метод запроса — ThenBy или ThenByDescending в зависимости от ascending значения. Следующий код создаст этот порядок:

 public static class QueryableExtensions
{
    public static IQueryable<T> OrderByPropertyOrField<T>(this IQueryable<T> queryable,
      string propertyOrFieldName, bool ascending = true)
    {
        var parameter = Expression.Parameter(queryable.ElementType, "x");
        var selector = Expression.PropertyOrField(parameter, propertyOrFieldName);

        var getLength = Expression.PropertyOrField(selector, "Length");
        var orderByLength = CreateOrderExpression(parameter,
          typeof(int),
          queryable.Expression, // order source collection
          getLength,
          ascending ? "OrderBy" : "OrderByDescending");

        var orderByValue = CreateOrderExpression(parameter,
          typeof(string),
          orderByLength, // order previous collection
          selector,
          ascending ? "ThenBy" : "ThenByDescending");

        return queryable.Provider.CreateQuery<T>(orderByValue);
    }

    private static Expression CreateOrderExpression(ParameterExpression parameter, Type keyType, Expression collection, Expression selector, string methodName)
    {
        return Expression.Call(
            typeof(Queryable),
            methodName,
            new[] { parameter.Type, keyType },
            collection,
            Expression.Lambda(selector, parameter)
        );
    }
}