I wrote the code below using this answer: LINQ to Entities does not recognize the method 'Method name' method
/// <summary>
/// Helper class to assit with ordering
/// </summary>
public static class QueryableHelper
{
public static IOrderedQueryable<TModel> OrderBy<TModel>(this IQueryable<TModel> q, string name, string orderType)
{
Type entityType = typeof(TModel);
PropertyInfo p = entityType.GetProperty(name);
MethodInfo m = typeof(QueryableHelper).GetMethod(orderType).MakeGenericMethod(entityType, p.PropertyType);
return (IOrderedQueryable<TModel>)m.Invoke(null, new object[] { q, p });
}
public static IOrderedQueryable<TModel> OrderByPropertyDescending<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p)
{
var expression = GetExpression<TModel, TRet>(q, p);
return q.OrderByDescending(expression);
}
public static IOrderedQueryable<TModel> OrderByProperty<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p)
{
var expression = GetExpression<TModel, TRet>(q, p);
return q.OrderBy(expression);
}
private static Expression<Func<TModel, TRet>> GetExpression<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p)
{
ParameterExpression pe = Expression.Parameter(typeof(TModel));
Expression se = Expression.Convert(Expression.Property(pe, p), typeof(TRet));
var expression = Expression.Lambda<Func<TModel, TRet>>(se, pe);
return expression;
}
}
I have removed some of the repetition, but there is still more I can remove.
I want to call this function directly:
OrderByPropertyDescending
Currently it is being called by this line:
MethodInfo m = typeof(QueryableHelper).GetMethod(orderType).MakeGenericMethod(entityType, p.PropertyType);
Is there a way to call this function directly eg like this:
var res = OrderByPropertyDescending<TModel, TRet>(q, p);
My problem is that I do not know what to pass in for TRet
Any ideas?
You can use Expression<Func<TModel, TProperty>>
as a type for property
instead of PropertyInfo
.
That will result in calls like: OrderByPropertyDescending(model, model => model.X)
, where all generic arguments are automatically figured.
Then, you'll need to fetch PropertyInfo
from given expression, so you'll just need to check type of given expression.
I've seen such an idea in Caliburn.Micro
- see, for example, their ExpressionExtensions
: https://github.com/Caliburn-Micro/Caliburn.Micro/blob/master/src/Caliburn.Micro.Core/ExpressionExtensions.cs
Actually, their GetMemberInfo
will work for you.