【问题标题】:C# How to use GetMethod to find a specific overload with a generic out parameter?C# 如何使用 GetMethod 查找具有通用输出参数的特定重载?
【发布时间】:2020-09-04 19:35:29
【问题描述】:

一切都在标题中,但让我放一些代码。 假设我们有一个包含两个同名方法的类:

class MyClass
{
  /// <summary>
  /// The first version
  /// </summary>
  public TItem Foo(long param1) { ... }
  /// <summary>
  /// Overload with a generic parameters
  /// </summary>
  public bool Foo<TItem>(out TItem item, long param1) { ... }
}

我们需要获取具有通用输出参数的第二个“Foo”方法的 MethodInfo:

    public class AnotherClass
    {
      public MethodInfo GetFooForType(Type typeOfItem)
      {
        // the answer is probably GetMethod with the right parameters
        return typeof(MyClass).GetMethod(???);
      }
    }

请注意:

  • 我尝试不使用 GetMethods 或 GetMember,因为它不雅且容易出现未来错误
  • 重命名任何 Foo 方法都不是一种选择(太容易了)。
  • 类型或 TItem 显然只在运行时才知道。
  • 我可能正在为 GetMethod 寻找正确的参数,但我可以接受任何建议(GetMethods 或 GetMember 除外)。
  • 我花了 1 小时在 StackOverflow 上搜索答案,但没有成功,但反射发展得如此之快,以至于周围有很多不相关的答案。在 stackoverflow 中添加日期过滤器可能是个好主意(或者可能是 .Net 框架版本过滤器?)
  • 非常欢迎您证明我错了,并找到我错过的明显答案!
  • 这不是 .Net Core 项目(MakeGenericMethodParameter 不是一个选项)
  • 我叫莫斯,我是个子弹瘾君子^^

【问题讨论】:

  • “...使用通用输出参数查找重载”可能会返回多个结果。最简单的机制是使用GetMethods 并过滤名称和参数,然后返回MethodInfo[] 或返回MethodInfo,如果有多个与GetMethod 相似的匹配项则返回异常。
  • 第一个版本从哪里得到TItem?我认为您需要为这两种方法提供更多上下文。
  • 试试type.GetMethod("Foo", new[] { Type.MakeGenericMethodParameter(0).MakeByRefType(), typeof(long) })
  • 添加了更多上下文。我试图避免 GetMethod。 TItem 可以是任何东西,它是方法的通用参数,而不是声明类型。
  • 我很确定您的问题(包括所有警告)的答案是“您不能那样做”。请参阅 2015 年 Marc Gravell 的 this answer。简短的版本是 Type.GetMethod 重载所需的类型仅存在于方法定义中。在您已经拥有该方法之前,您无法创建正确的泛型参数类型!如果您将 MyClass 设为泛型(例如 MyClass&lt;TItem&gt;),现在您可以使用 Type.GetMethod,因为现在您可以创建正确的泛型类型(根据@GuruStron 答案的第一部分) .

标签: c# generics reflection getmethod


【解决方案1】:

如果你的类是通用类(如果不是,你的代码会给你一个关于覆盖的警告)你可以使用typeof(MyClass&lt;&gt;).GetGenericArguments().First().MakeByRefType()

class MyClass<TItem>
{
    /// <summary>
    /// The first version
    /// </summary>
    public TItem Foo(long param1) { throw new Exception(); }
    /// <summary>
    /// Overload with a generic parameters
    /// </summary>
    public bool Foo(out TItem item, long param1) { throw new Exception();}
}

var genericMI = typeof(MyClass<>).GetMethod(
    "Foo",
    new[] 
    { 
         typeof(MyClass<>).GetGenericArguments().First().MakeByRefType(), 
         typeof(long)
    });

对于非泛型,您可以使用Type.MakeGenericMethodParameter(0).MakeByRefType()(实际上它可以与MyClass&lt;T&gt; 一起使用,并且也可以覆盖Foo&lt;T&gt; 中的泛型参数):

class MyClass
{
    /// <summary>
    /// The first version
    /// </summary>
    public int Foo(long param1) { throw new Exception(); }
    /// <summary>
    /// Overload with a generic parameters
    /// </summary>
    public bool Foo<TItem>(out TItem item, long param1) { throw new Exception();}
}

var genericMI = typeof(MyClass).GetMethod(
        "Foo",
        new[] 
        {
            Type.MakeGenericMethodParameter(0).MakeByRefType(),
            typeof(long)
        });

【讨论】:

  • 不幸的是,TItem 是方法的泛型参数,而不是声明类型。我添加了很多上下文来说明这一点。遗憾的是我不能使用 .Net Core...
  • @Mose 是的,它是来自 .NET Core 的方法。问题中的代码也不会编译。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
  • 2013-07-10
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
相关资源
最近更新 更多