Hi,
Haven't used this package (yet) but it seem to have a lot of functionality that I might use as my project evolves. It also lacks the only functionality I currently need :) Since the reflection calls, expression tree parsing is probably more efficient than my code I thought to create a PR with a new feature.
To the point: I use EF Core (currently in a MVC application) with an extension OrderBy that takes a string Property [ASC | DESC] | ["," ...] (abusing BNF ;). However I need to be able to order by more complex expressions such as p => p.A.Cost + p.B.Cost + ... etc where, in this example, Cost might be nullable. So I also need to sort null values last, if desired.
So I've created a class Orderable
public class Orderable
{
internal Orderable(string expression)
{
var parts = expression.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0 || parts.Length > 2)
{
throw new ArgumentException("Expression must be of form 'TKey [ASC | DESC]'", nameof(expression));
}
Property = parts[0];
if (parts.Length == 2)
{
Descending = "DESC".Equals(parts[1], StringComparison.OrdinalIgnoreCase);
}
}
public Orderable(Expression expression, Type expressionType, bool descending = false, bool nullLast = true)
{
Expression = expression;
ExpressionType = expressionType;
Descending = descending;
NullLast = nullLast;
}
public static Orderable Create<TModel, TKey>(Expression<Func<TModel, TKey>> expression, bool descending = false, bool nullLast = true)
{
return new Orderable(expression, expression.ReturnType, descending, nullLast);
}
public Expression Expression { get; }
public Type ExpressionType { get; set; }
public string Parameter { get; set; }
public bool NullLast { get; }
public string Property { get; }
public bool Descending { get; }
}
Extension method
public static IQueryable<T> SortBy<T>(this IQueryable<T> source, params Ordering[] orderings) where T : class
{
// Argument checks ommitted
string methodName = "";
IQueryable<T> query = source;
foreach (var ordering in orderings)
{
if (string.IsNullOrEmpty(methodName))
{
methodName = ordering.Descending ? "OrderByDescending" : "OrderBy";
}
else
{
methodName = ordering.Descending ? "ThenByDescending" : "ThenBy";
}
ParameterExpression parameter = Expression.Parameter(source.ElementType, string.Empty);
LambdaExpression lambda;
Expression propertyExpression;
Type propertyType;
if (string.IsNullOrEmpty(ordering.Property))
{
// Build directly from Expression
propertyType = ordering.ExpressionType;
lambda = (LambdaExpression)ordering.Expression;
if (ordering.NullLast)
{
// TODO: Check type is nullable
try
{
var op = lambda.Body;
var equal = Expression.Equal(op, Expression.Constant(null));
var condition = Expression.Condition(equal, Expression.Constant(1), Expression.Constant(0));
Expression mce = Expression.Call(
typeof(Queryable),
methodName,
new[] { source.ElementType, typeof(int) },
query.Expression,
Expression.Quote(condition));
query = (IQueryable<T>)query.Provider.CreateQuery(mce);
}
catch (Exception)
{
}
}
}
else
{
lambda = CreateLambdaExpression(parameter, ordering, out propertyExpression);
propertyType = propertyExpression.Type;
}
Expression methodCallExpression = Expression.Call(
typeof(Queryable),
methodName,
new[] { source.ElementType, propertyType },
query.Expression,
Expression.Quote(lambda));
query = (IQueryable<T>)query.Provider.CreateQuery(methodCallExpression);
}
So, is this something that is align with the project? If so I'm happy to create a PR.
Regards
Hi,
Haven't used this package (yet) but it seem to have a lot of functionality that I might use as my project evolves. It also lacks the only functionality I currently need :) Since the reflection calls, expression tree parsing is probably more efficient than my code I thought to create a PR with a new feature.
To the point: I use EF Core (currently in a MVC application) with an extension
OrderBythat takes a stringProperty [ASC | DESC] | ["," ...](abusing BNF ;). However I need to be able to order by more complex expressions such asp => p.A.Cost + p.B.Cost + ...etc where, in this example,Costmight be nullable. So I also need to sort null values last, if desired.So I've created a class
OrderableExtension method
So, is this something that is align with the project? If so I'm happy to create a PR.
Regards