Creating Dynamic Func <IQueryable <TEntity>, IOrderedQueryable <TEntity>>?

I want to dynamically create Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> from the SortingItems list. I want to say that I want to create the following expression:

entity => entity.OrderBy(c => c.Id).ThenBy(c => c.Name).ThenByDescending(c => c.LastName)

Below is my code:

 [DataContract] public class SortingItem { [DataMember] public string PropertySelectorString { get; set; } [DataMember] public SortingDirectionsEnum SortingDirections { get; set; } } [DataContract] public enum SortingDirectionsEnum { [EnumMember] Descending = 0, [EnumMember] Ascending = 1 } public Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> GetSortingFunc<TEntity>() { _entityType = typeof(TEntity); _parameterExpression = Expression.Parameter(_entityType, "entity"); _iQueryableParameterExpression = Expression.Parameter(typeof(IQueryable<TEntity>), "f"); MethodInfo orderByMethodInfo = null; Expression resultExpression = null; foreach (SortingItem sortingItem in SortingItems) { MemberExpression memberExpression = GetLeftSide(sortingItem.PropertySelectorString, _entityType, _parameterExpression); // I'm dead sure about working this line switch (sortingItem.SortingDirections) { case SortingDirectionsEnum.Descending: orderByMethodInfo = typeof(Queryable).GetMethods().First(method => method.Name == "OrderBy" && method.GetParameters().Length == 2).MakeGenericMethod(_entityType, memberExpression.Type); if (resultExpression != null) orderByMethodInfo = typeof(Queryable).GetMethods().First(method => method.Name == "ThenBy" && method.GetParameters().Length == 2).MakeGenericMethod(_entityType, memberExpression.Type); break; case SortingDirectionsEnum.Ascending: orderByMethodInfo = typeof(Queryable).GetMethods().First(method => method.Name == "OrderByDescending" && method.GetParameters().Length == 2).MakeGenericMethod(_entityType, memberExpression.Type); if (resultExpression != null) orderByMethodInfo = typeof(Queryable).GetMethods().First(method => method.Name == "ThenByDescending" && method.GetParameters().Length == 2).MakeGenericMethod(_entityType, memberExpression.Type); break; } MethodCallExpression methodCallExpression; if (resultExpression != null) // Exception // An unhandled exception of type 'System.ArgumentException' occurred in System.Core.dll // Additional information: Incorrect number of arguments supplied for call to method 'System.Linq.IOrderedQueryable`1[ConsoleApplication1.User] ThenBy[User,Int32](System.Linq.IOrderedQueryable`1[ConsoleApplication1.User], System.Linq.Expressions.Expression`1[System.Func`2[ConsoleApplication1.User,System.Int32]])' methodCallExpression = Expression.Call(orderByMethodInfo, _iQueryableParameterExpression, resultExpression, Expression.Lambda(memberExpression, _parameterExpression)); else methodCallExpression = Expression.Call(orderByMethodInfo, _iQueryableParameterExpression, Expression.Lambda(memberExpression, _parameterExpression)); resultExpression = Expression.Lambda(methodCallExpression, _iQueryableParameterExpression); } Expression<Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>> lambdaExpression = Expression.Lambda<Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>>(resultExpression, _parameterExpression); return lambdaExpression.Compile(); } 

OK to create {f.OrderBy(entity => entity.Id)} or {f.ThenBy(entity => entity.Name)} separately, but I get an exception in the next line

 methodCallExpression = Expression.Call(orderByMethodInfo, _iQueryableParameterExpression, resultExpression, Expression.Lambda(memberExpression, _parameterExpression)); 

How to use Expression.Call to combine {f.OrderBy(entity => entity.Id)} with {f.ThenBy(entity => entity.Name)} , ....?

+5
source share
1 answer

I suggest you not write such code, as it is difficult to read. I had to support these monsters in the past.

If you are really interested in a solution, you can download DynamicLINQ, and then your request will look like this:

 public string GetSortCriteria(this SortingItem item){ return string.Format("{0} {1}", item.PropertySelectorString, item.SortingDirections == SortingDirectionsEnum.Descending ? "DESC" : "ASC"); } // later: var mergedSortCriteria= string.Join(",", SortingItems.Select(item => item.GetSortCriteria()); Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> myFunc = source => source.OrderBy("id " + mergedSortCriteria); 
+2
source

Source: https://habr.com/ru/post/1208350/


All Articles