Change code snippet in expressions

Something is missing me, and I'm not quite sure that I don't have much experience with LINQ expressions.

I am trying to change the following code snippet in an expression.

MethodInfo orderByMethod = (from method in typeof(QueryableExtensions).GetMethods() where method.Name == "OrderBy" && method.GetGenericArguments().Length > 0 select method).First(); MethodInfo orderByGenericMethod = orderByMethod.MakeGenericMethod(new[] { queryable.ElementType }); IQueryable queryable = orderByGenericMethod.Invoke(null, new object[] { queryable, sorting.ColumnName, sorting.Direction }) as IQueryable; 

Here is my attempt.

 Expression orderByMethodExpression = Expression.Call(typeof(QueryableExtensions), "OrderBy", new[] { queryable.ElementType }, Expression.Constant(queryable), Expression.Constant(sorting.ColumnName), Expression.Constant(sorting.Direction)); IQueryable queryable = queryable.Provider.CreateQuery(orderByMethodExpression) 

The corresponding code.

 SortingExpression sorting = SortingExpression.Create(arguments.SortExpression); IQueryable queryable = enumerable.AsQueryable(); if (sorting != null) { MethodInfo orderByMethod = (from method in typeof(QueryableExtensions).GetMethods() where method.Name == "OrderBy" && method.GetGenericArguments().Length > 0 select method).First(); MethodInfo orderByGenericMethod = orderByMethod.MakeGenericMethod(new[] { queryable.ElementType }); queryable = orderByGenericMethod.Invoke(null, new object[] { queryable, sorting.ColumnName, sorting.Direction }) as IQueryable; } object[] items = Enumerable.Cast<object>(queryable).ToArray(); arguments.TotalRowCount = items.Length; enumerable = items; 

The error I am getting.

There is no general "OrderBy" method in the type "Shilony.Web.UI.WebControls.QueryableExtensions" is compatible with the arguments and arguments of the supplied type. No type arguments should be provided unless the method is general.

Just to clarify OrderBy, my own extension method here is the method signature.

 public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName, string direction) where TSource : class 

Just to understand what's wrong, I changed it to this.

 MethodInfo orderByMethod = (from method in typeof(QueryableExtensions).GetMethods() where method.Name == "OrderBy" && method.GetGenericArguments().Length > 0 select method).First(); MethodInfo orderByGenericMethod = orderByMethod.MakeGenericMethod(new[] { queryable.ElementType }); Expression orderByMethodExpression = Expression.Call(orderByGenericMethod, Expression.Constant(queryable, typeof(IQueryable)), Expression.Constant(sorting.ColumnName, typeof(string)), Expression.Constant(sorting.Direction, typeof(string))); queryable = queryable.Provider.CreateQuery(orderByMethodExpression); 

And now I get this error.

An expression of type "System.Linq.IQueryable" cannot be used for a parameter of type "System.Linq.IQueryable 1[Shilony.DomainLayer.DomainObjects.Customer]' of method 'System.Linq.IQueryable 1 [Shilony.DomainLayer.DomainObjects.Customer] OrderBy [Customer] (System.Linq.IQueryable`) 1 [Shilony.DomainLayer.DomainObjects.Customer], System.String, System.String) '

I do not get it when I call it with the same arguments as it works, but when I try to turn it all into an expression, it will not work.

+4
source share
2 answers

Do not pay attention to what I understood, I had to study the details more carefully.

Before I made an call to Expression.Call, the expression tree looks like this.

{System.Linq.IQueryable`1 [Shilony.DomainLayer.DomainObjects.Customer] OrderBy [Customer] ( System.Linq.IQueryable, System.String, System.String )}

After I made the call to Expression.Call, the expression will turn into the following.

{System.Collections.Generic.List`1 [Shilony.DomainLayer.DomainObjects.Customer] .OrderBy ("LastName", null)}

The problem and my mistake is that I tried to pass the CreateQuery expression that was received as a result of the call.

The return type is a list, and since OrderBy is an IQueryable extension method, there is such a method, so it tries to call it again, the problem does not work, because now OrderBy should be called with a different number of arguments System.Linq.IQueryable should be excluded, and because of this, it throws the following exception.

There is no general "OrderBy" method in the type "Shilony.Web.UI.WebControls.QueryableExtensions" is compatible with the arguments and arguments of the supplied type. No type arguments should be provided unless the method is general.

Here is the solution.

 Expression orderByExtensionMethodExpression = Expression.Call(typeof(QueryableExtensions), "OrderBy", new[] { queryable.ElementType }, Expression.Constant(queryable), Expression.Constant(sorting.ColumnName), Expression.Constant(sorting.Direction, typeof(string))); queryable = Expression.Lambda(orderByExtensionMethodExpression).Compile().DynamicInvoke() as IQueryable; 
+3
source

You do not need to manually create an expression tree. You can get the compiler to do this for you in a much more understandable way. This will simplify reading and maintenance.

 Expression<Func<string, string, IOrderedQueryable<T>>> GetOrderByExpression<T>(IQueryable<T> query) { //the compiler will compile the anonymous method into an expression tree Expression<Func<string, string, IOrderedQueryable<T>>> orderByMethodExpression = (string column, string direction) => query.OrderBy(column, direction); //return the expression return orderByMethodExpression; } 
0
source

All Articles