当前位置:  开发笔记 > 编程语言 > 正文

在不使用GetMethods的情况下获取泛型方法

如何解决《在不使用GetMethods的情况下获取泛型方法》经验,为你挑选了3个好方法。

我想得到方法System.Linq.Queryable.OrderyBy(the IQueryable source, Expression> keySelector)方法,但我不断提出空值.

var type = typeof(T);
var propertyInfo = type.GetProperty(group.PropertyName);
var propertyType = propertyInfo.PropertyType;

var sorterType = typeof(Func<,>).MakeGenericType(type, propertyType);
var expressionType = typeof(Expression<>).MakeGenericType(sorterType);

var queryType = typeof(IQueryable);

var orderBy = typeof(System.Linq.Queryable).GetMethod("OrderBy", new[] { queryType, expressionType }); /// is always null.

有没有人有任何见解?我宁愿不循环GetMethods结果.



1> Neil..:

解决了(通过黑客攻击LINQ)!

我在研究同样的问题时看到了你的问题.在找不到好的解决方案之后,我有了查看LINQ表达式树的想法.这是我想出的:

public static MethodInfo GetOrderByMethod()
{
    Func fakeKeySelector = element => default(TSortKey);

    Expression, IOrderedEnumerable>> lamda
        = list => list.OrderBy(fakeKeySelector);

    return (lamda.Body as MethodCallExpression).Method;
}

static void Main(string[] args)
{
    List ints = new List() { 9, 10, 3 };
    MethodInfo mi = GetOrderByMethod();           
    Func keySelector = i => i.ToString();
    IEnumerable sortedList = mi.Invoke(null, new object[] { ints, 
                                                                 keySelector }
                                           ) as IEnumerable;

    foreach (int i in sortedList)
    {
        Console.WriteLine(i);
    }
}

输出:10 3 9

编辑:如果你在编译时不知道类型,这里是如何获取方法:

public static MethodInfo GetOrderByMethod(Type elementType, Type sortKeyType)
{
    MethodInfo mi = typeof(Program).GetMethod("GetOrderByMethod", Type.EmptyTypes);

    var getOrderByMethod = mi.MakeGenericMethod(new Type[] { elementType,
                                                             sortKeyType });
    return getOrderByMethod.Invoke(null, new object[] { }) as MethodInfo;
}

一定要用typeof(WhateverClassYouDeclareTheseMethodsIn)替换typeof(Program).


你没有循环使用Type.GetMethods结果的替代方法让我很好奇:它的表现如何?根据我的预期,循环实际上是[更快](http://www.damirscorner.com/CallAGenericExtensionMethodUsingReflection.aspx).

2> Jon Skeet..:

作为扩展方法的解决方案的变体:

public static class TypeExtensions
{
    private static readonly Func> ParameterTypeProjection = 
        method => method.GetParameters()
                        .Select(p => p.ParameterType.GetGenericTypeDefinition());

    public static MethodInfo GetGenericMethod(this Type type, string name, params Type[] parameterTypes)
    {
        return (from method in type.GetMethods()
                where method.Name == name
                where parameterTypes.SequenceEqual(ParameterTypeProjection(method))
                select method).SingleOrDefault();
    }
}


我应该能够澄清:我有MyClass.MyMethod (T gnrc).如果我想调用上面的GetGenericMethod来获取MyMethod的MethodInfo,我会将typeof(MyClass)作为第一个param,"MyMethod"作为第二个,但是我将作为第三个传递给什么?
@ dudeNumber4:啊,我明白了.你不会,基本上 - 你必须调用`GetMethods`然后自己过滤它.这是反射API的一个弱点.

3> 小智..:

我认为以下扩展方法可以解决该问题:

public static MethodInfo GetGenericMethod(
  this Type type, string name, Type[] generic_type_args, Type[] param_types, bool complain = true)
{
  foreach (MethodInfo m in type.GetMethods())
    if (m.Name == name)
    {
      ParameterInfo[] pa = m.GetParameters();
      if (pa.Length == param_types.Length)
      {
        MethodInfo c = m.MakeGenericMethod(generic_type_args);
        if (c.GetParameters().Select(p => p.ParameterType).SequenceEqual(param_types))
          return c;
      }
    }
  if (complain)
    throw new Exception("Could not find a method matching the signature " + type + "." + name +
      "<" + String.Join(", ", generic_type_args.AsEnumerable()) + ">" +
      "(" + String.Join(", ", param_types.AsEnumerable()) + ").");
  return null;
}

该调用将类似于(仅更改原始代码的最后一行):

var type = typeof(T);  
var propertyInfo = type.GetProperty(group.PropertyName);  
var propertyType = propertyInfo.PropertyType;  

var sorterType = typeof(Func<,>).MakeGenericType(type, propertyType);  
var expressionType = typeof(Expression<>).MakeGenericType(sorterType);  

var queryType = typeof(IQueryable);  

var orderBy = typeof(Queryable).GetGenericMethod("OrderBy",
                                                 new Type[] { type, propertyType },
                                                 new[] { queryType, expressionType });

与其他解决方案的不同之处在于:生成的方法与参数类型完全匹配,而不仅仅是它们的通用基本类型。

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有