使用反射获取OrderBy方法

时间:2015-04-01 09:11:57

标签: c# asp.net-mvc reflection expression-trees

我想为我的项目实现通用寻呼机和过滤视图模型,而我仍然坚持使用反射获取OrderBy方法。以下是我尝试过的内容,但null继续获取methodInfo。我似乎将错误的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;
    }

1 个答案:

答案 0 :(得分:1)

然后Enumerable.OrderBy扩展方法是一种静态方法,因此您必须使用重载到GetMethod,您可以在其中指定BindingFlagsBindingFlags.Static | BindingFlags.Public而不是默认{{1} }})。

你还必须为方法指定两个参数 - 从语法上看,它看起来只有一个参数,但因为它是一个扩展方法,所以你需要指定第二个参数。

这是你想通过反思获得的方法:

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); ,但是您必须修改剩余的两行代码,因为此方法是静态方法,您必须在MethodInfo中指定一个空实例。