C# 以编程方式创建用于对IQueryable排序的谓词
我想为C# 以编程方式创建用于对IQueryable排序的谓词,c#,linq,expression,C#,Linq,Expression,我想为IQueryable接口创建一个通用扩展方法,它将接受一些字符串输入并生成一个IOrderedQueryable输出 我曾尝试通过编程方式创建表达式,但TKey只能在运行时确定 这是我到目前为止提出的实现 publicstaticiorderedqueryable排序(this IQueryable this,string排序),其中T:class { var类型=类型(T); var param=表达式参数(类型为“x”); var(isDescending,normalizedSort
IQueryable
接口创建一个通用扩展方法,它将接受一些字符串输入并生成一个IOrderedQueryable
输出
我曾尝试通过编程方式创建表达式
,但TKey
只能在运行时确定
这是我到目前为止提出的实现
publicstaticiorderedqueryable排序(this IQueryable this,string排序),其中T:class
{
var类型=类型(T);
var param=表达式参数(类型为“x”);
var(isDescending,normalizedSortParam)=NormalizeSortParam(sort);
MemberExpression propertyExpression;
尝试
{
propertyExpression=Expression.PropertyOrField(param,normalizedSortParam);
}
捕获(异常)
{
propertyExpression=Expression.Property(param,“Id”);
}
var outputType=propertyExpression.Type;
var filterExpression=Expression.Lambda(propertyExpression,param);
return isDescending?This.OrderByDescending(filterExpression):This.OrderBy(filterExpression);
}
对于上下文,Id
字段存在于将调用排序方法的所有类型T上
这没有得到成功编译(如预期的那样),但我不知道如何在运行时指定输出类型。在这种情况下,最简单的方法是使用
OrderBy
/OrderByDescending
方法构建表达式并创建新的查询表:
public static IOrderedQueryable<T> Sort<T>(this IQueryable<T> query, string sort) where T : class
{
Type type = typeof(T);
ParameterExpression param = Expression.Parameter(type, "x");
var (isDescending, normalizedSortParam) = NormalizeSortParam(sort);
MemberExpression propertyExpression;
try
{
propertyExpression = Expression.PropertyOrField(param, normalizedSortParam);
}
catch(ArgumentException)
{
propertyExpression = Expression.Property(param, "Id");
}
Type outputType = propertyExpression.Type;
LambdaExpression filterExpression = Expression.Lambda(propertyExpression, param);
// Call OrderBy or OrderByDescending on original query expression
MethodCallExpression orderedExpression = Expression.Call(
typeof(Queryable),
isDescending ? "OrderByDescending" : "OrderBy",
new []{ typeof(T), outputType },
new [] { query.Expression, filterExpression }
);
// Create new query from orderedExpression
return (IOrderedQueryable<T>)query.Provider.CreateQuery<T>(orderedExpression);
}
publicstaticiorderedqueryable排序(此IQueryable查询,字符串排序),其中T:class
{
类型=类型(T);
ParameterExpression param=表达式参数(类型为“x”);
var(isDescending,normalizedSortParam)=NormalizeSortParam(sort);
MemberExpression propertyExpression;
尝试
{
propertyExpression=Expression.PropertyOrField(param,normalizedSortParam);
}
捕获(异常)
{
propertyExpression=Expression.Property(param,“Id”);
}
类型outputType=propertyExpression.Type;
LambdaExpression filterExpression=Expression.Lambda(propertyExpression,param);
//对原始查询表达式调用OrderBy或OrderByDescending
MethodCallExpression orderedExpression=Expression.Call(
类型(可查询),
isDescending?“OrderByDescending”:“OrderBy”,
新[]{typeof(T),outputType},
新[]{query.Expression,filterExpression}
);
//从orderedExpression创建新查询
return(IOrderedQueryable)query.Provider.CreateQuery(orderedExpression);
}
在过去,我对T使用了另一种类型约束,例如,其中T:IIdentifiable,class。(具有id属性/get访问器的IIIdentifiable接口)请参阅forExpression.Lambda
-其中一些接口将类型作为运行时参数,而不是泛型类型参数。您可能还需要通过反射来调用OrderBy
,但随后可以将结果转换回IOrderedQueryable