使用反射获取 OrderBy 方法
Get OrderBy method using reflection
我想为我的项目实现通用寻呼机和过滤器视图模型,但我坚持使用反射获取 OrderBy 方法。这是我尝试过的方法,但是 methodInfo
的结果一直是 null
。似乎我将错误的 Type[]
参数传递给 GetMethod()
方法,但我无法正确处理。
protected virtual Expression<Func<T, IComparable>> GetOrderByExpression()
{
var type = typeof(T);
var property = type.GetProperty("DataSetName");
var parameter = Expression.Parameter(type, "x");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExp = Expression.Lambda(propertyAccess, parameter);
var methodInfo = typeof(Enumerable).GetMethod("OrderBy", new Type[] { orderByExp.Body.Type });
var predicateBody = Expression.Call(propertyAccess, methodInfo, orderByExp);
var expression = Expression.Lambda<Func<T, IComparable>>(predicateBody, parameter);
return expression;
}
然后 Enumerable.OrderBy
扩展方法是一个静态方法,因此您必须使用对 GetMethod
的重载,您可以在其中指定 BindingFlags
(BindingFlags.Static | BindingFlags.Public
而不是默认的 BindingFlags.Instance | BindingFlags.Public
).
您还必须为该方法指定两个参数 - 从语法上看,它似乎只有一个参数,但因为它是一种扩展方法,所以您必须指定第二个参数。
这是你想通过反射得到的方法:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
您需要两种参数类型:
var sourceType = typeof(IEnumerable<>).MakeGenericType(type);
var keySelectorType = orderByExp.Compile().GetType();
似乎只有执行搜索才能获得具有泛型参数的方法的特定重载。幸运的是,Enumerable.OrderBy
的重载只有两个,您想要的是带有两个参数的那个:
var genericMethodInfo = typeof(Enumerable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.First(mi => mi.Name == "OrderBy" && mi.GetParameters().Length == 2);
var methodInfo = genericMethodInfo.MakeGenericMethod(sourceType, keySelectorType);
这个returns想要的MethodInfo
,但是你将不得不修改剩下的两行代码,因为这个方法是一个静态方法,你必须在[=20中指定一个空实例=].
我想为我的项目实现通用寻呼机和过滤器视图模型,但我坚持使用反射获取 OrderBy 方法。这是我尝试过的方法,但是 methodInfo
的结果一直是 null
。似乎我将错误的 Type[]
参数传递给 GetMethod()
方法,但我无法正确处理。
protected virtual Expression<Func<T, IComparable>> GetOrderByExpression()
{
var type = typeof(T);
var property = type.GetProperty("DataSetName");
var parameter = Expression.Parameter(type, "x");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExp = Expression.Lambda(propertyAccess, parameter);
var methodInfo = typeof(Enumerable).GetMethod("OrderBy", new Type[] { orderByExp.Body.Type });
var predicateBody = Expression.Call(propertyAccess, methodInfo, orderByExp);
var expression = Expression.Lambda<Func<T, IComparable>>(predicateBody, parameter);
return expression;
}
然后 Enumerable.OrderBy
扩展方法是一个静态方法,因此您必须使用对 GetMethod
的重载,您可以在其中指定 BindingFlags
(BindingFlags.Static | BindingFlags.Public
而不是默认的 BindingFlags.Instance | BindingFlags.Public
).
您还必须为该方法指定两个参数 - 从语法上看,它似乎只有一个参数,但因为它是一种扩展方法,所以您必须指定第二个参数。
这是你想通过反射得到的方法:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
您需要两种参数类型:
var sourceType = typeof(IEnumerable<>).MakeGenericType(type);
var keySelectorType = orderByExp.Compile().GetType();
似乎只有执行搜索才能获得具有泛型参数的方法的特定重载。幸运的是,Enumerable.OrderBy
的重载只有两个,您想要的是带有两个参数的那个:
var genericMethodInfo = typeof(Enumerable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.First(mi => mi.Name == "OrderBy" && mi.GetParameters().Length == 2);
var methodInfo = genericMethodInfo.MakeGenericMethod(sourceType, keySelectorType);
这个returns想要的MethodInfo
,但是你将不得不修改剩下的两行代码,因为这个方法是一个静态方法,你必须在[=20中指定一个空实例=].