如何直接调用OrderByPropertyDescending?TRet类型参数该传入什么?
Hey there! Let's tackle this problem head-on. The core issue here is that TRet (the type of the property you're sorting by) is only known at runtime (via p.PropertyType), so you can't explicitly specify it at compile time to call OrderByPropertyDescending<TModel, TRet> directly. Instead, we can refactor your helper class to eliminate the need for those intermediate generic methods and build the expression tree directly to interact with LINQ's native OrderBy/OrderByDescending methods.
Refactored QueryableHelper Class
Here's a streamlined, optimized version that cuts out redundant reflection calls and focuses on direct LINQ method invocation:
/// <summary> /// Helper class to assist with ordering Queryable collections by property name /// </summary> public static class QueryableHelper { public static IOrderedQueryable<TModel> OrderBy<TModel>(this IQueryable<TModel> query, string propertyName, string orderType) { Type modelType = typeof(TModel); PropertyInfo property = modelType.GetProperty(propertyName) ?? throw new ArgumentException($"Property '{propertyName}' does not exist on type {modelType.FullName}"); // Build the expression tree for the property access (x => x.PropertyName) ParameterExpression parameter = Expression.Parameter(modelType, "x"); MemberExpression propertyAccess = Expression.Property(parameter, property); LambdaExpression orderLambda = Expression.Lambda(propertyAccess, parameter); // Retrieve the correct LINQ static method (OrderBy or OrderByDescending) MethodInfo orderMethod = typeof(Queryable).GetMethods() .First(method => method.Name == orderType && method.GetParameters().Length == 2) .MakeGenericMethod(modelType, property.PropertyType); // Invoke the method and cast the result to the ordered query type return (IOrderedQueryable<TModel>)orderMethod.Invoke(null, new object[] { query, orderLambda }); } }
Key Improvements & Explanations:
- Removed redundant generic methods: We no longer need
OrderByPropertyorOrderByPropertyDescending—all logic lives directly in the singleOrderByextension method, eliminating code duplication. - Direct LINQ interaction: Instead of reflecting to call your own helper methods, we invoke LINQ's native sorting methods directly. This cuts out unnecessary layers and makes the code more efficient.
- Robust error handling: We added a check to ensure the requested property exists, throwing a clear exception if it doesn't—making the helper more reliable for production use.
- Why direct
OrderByPropertyDescendingisn't possible: C# requires generic type parameters to be known at compile time, butTRet(the property type) is only determined at runtime when you fetchp.PropertyType. This means there's no way to explicitly specifyTRetin a direct method call without reflection. The refactored approach bypasses this limitation entirely by working with non-generic expression trees.
Usage Example
You can use the updated helper just like your original implementation:
// Order users by "Name" in ascending order var orderedAsc = dbContext.Users.OrderBy("Name", "OrderBy"); // Order users by "Age" in descending order var orderedDesc = dbContext.Users.OrderBy("Age", "OrderByDescending");
内容的提问来源于stack exchange,提问作者Alex

