public static IQueryable<TResult> ApplySortFilter<T, TResult>(this IQueryable<T> query, string columnName)
where T : EntityObject
{
var param = Expression.Parameter(typeof(T), "o");
var body = Expression.PropertyOrField(param,columnName);
var sortExpression = Expression.Lambda(body, param);
return query.OrderBy(sortExpression);
}
Parce que le type de OrderBy n'est pas déduit de sortExpression, je dois le spécifier comme ceci au moment de l'exécution:
var sortExpression = Expression.Lambda<T, TSortColumn>(body, param);
Ou
return query.OrderBy<T, TSortColumn>(sortExpression);
Je ne pense pas que cela soit possible cependant, car TSortColumn ne peut être déterminé que pendant l'exécution.
Y a-t-il un moyen de contourner ceci?
Nous avons fait quelque chose de similaire (pas à 100%, mais similaire) dans un projet LINQ to SQL. Voici le code:
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) {
var type = typeof(T);
var property = type.GetProperty(ordering);
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExp = Expression.Lambda(propertyAccess, parameter);
MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
return source.Provider.CreateQuery<T>(resultExp);
}
Nous n’avions pas réellement utilisé un générique, nous avions une classe connue, mais cela devrait fonctionner sur un générique (j’ai mis l’espace générique générique à la place.
Edit: Pour un ordre décroissant, passez OrderByDescending
au lieu de "OrderBy":
MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderByDescending", new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
Vous pouvez également utiliser Dynamic Linq
C # télécharger ici http://msdn.microsoft.com/en-us/vcsharp/bb894665.aspx
Ensuite, ajoutez simplement le paramètre using Linq.Dynamic; et vous obtenez automatiquement 2 méthodes d'extension supplémentaires qui peuvent être utilisées comme ceci
return query.OrderBy("StringColumnName");