将从接口类型获取的 MethodInfo 对象转换为 C# 中实现类型上相应的 MethodInfo 对象?

2023-12-21

我的问题是:如果我有 MethodInfo 对象,用于从接口类型获取的方法,并且我还有实现此接口的类的 Type 对象,但它通过显式实现来实现所述方法,如何正确获取该类中实现方法对应的MethodInfo对象?

我需要这样做的原因是实现方法可以应用一些属性,并且我需要通过反射找到这些属性,但是需要查找这些属性的类只有实现类的对象引用,并且类型接口的对象(+相应的 MethodInfo 对象)。

所以,假设我有以下程序:

using System;
using System.Reflection;

namespace ConsoleApplication8
{
    public interface ITest
    {
        void Test();
    }

    public class Test : ITest
    {
        void ITest.Test()
        {
            throw new NotImplementedException();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Type interfaceType = typeof(ITest);
            Type classType = typeof(Test);

            MethodInfo testMethodViaInterface =
                interfaceType.GetMethods()[0];
            MethodInfo implementingMethod =
                classType.GetMethod(/* ??? */"Test");

            Console.Out.WriteLine("interface: " +
                testMethodViaInterface.Name);
            if (implementingMethod != null)
                Console.Out.WriteLine("class: " +
                    implementingMethod.Name);
            else
                Console.Out.WriteLine("class: unable to locate");

            Console.Out.Write("Press enter to exit...");
            Console.In.ReadLine();
        }
    }
}

运行这个给我:

interface: Test
class: unable to locate
Press enter to exit...

在代码中,有一个带有 ??? 的 .GetMethod 调用。评论。这部分是我需要帮助的。要么我需要在这里指定(并且我已经测试了很多,这使我采用了另一种方式),要么我需要用什么来替换此代码。

由于我使用了接口中方法的显式实现,因此该方法的实际名称不仅仅是“Test”。如果我使用以下代码转储类类型的 GetMethods() 数组的全部内容:

foreach (var mi in classType.GetMethods(
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
    Console.Out.WriteLine(mi.Name);
}

然后我得到这个:

ConsoleApplication8.ITest.Test         <-- this is the one I want
ToString
Equals
GetHashCode
GetType
Finalize
MemberwiseClone

显然,该名称前面有接口的全名及其命名空间。但是,由于重载,看起来我必须做的是在类中找到所有此类实现方法(即假设有多个随参数变化的 Test 方法),然后比较参数。

有更容易的方法吗?基本上,一旦我从接口中获得了某个方法的 MethodInfo 对象,我就想通过获取其 MethodInfo 对象来找到实现该方法的类的确切方法。

请注意,我在这里处于一个循环的情况,所以如果我必须循环遍历类中的方法以从接口中找到确切的方法,那没关系,只要我有一个好的方法来识别何时找到了正确对象,真爱。

我尝试像这样更改上面的循环:

foreach (var mi in classType.GetMethods(
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
    if (mi.GetBaseDefinition() == testMethodViaInterface)
        Console.Out.WriteLine(mi.Name);
}

这没有打印出任何东西,所以很清楚GetBaseDefinition这种方法上的 不指向接口中的 MethodInfo 对象。

有什么指点吗?


供将来参考,如果其他人有兴趣,请提供给我的解决方案@格雷格比奇 https://stackoverflow.com/users/13552/greg-beech here https://stackoverflow.com/questions/1525096/translating-a-methodinfo-object-obtained-from-an-interface-type-to-the-correspon/1525141#1525141是要使用Type.GetInterfaceMap http://msdn.microsoft.com/en-us/library/system.type.getinterfacemap.aspx.

这是修改后的程序代码,底部有一个扩展方法。

using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;

namespace ConsoleApplication8
{
    public interface ITest
    {
        void Test();
    }

    public class Test : ITest
    {
        void ITest.Test()
        {
            throw new NotImplementedException();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Type interfaceType = typeof(ITest);
            Type classType = typeof(Test);

            InterfaceMapping map = classType.GetInterfaceMap(interfaceType);

            MethodInfo testMethodViaInterface = interfaceType.GetMethods()[0];
            MethodInfo implementingMethod = testMethodViaInterface.GetImplementingMethod(classType);

            Console.Out.WriteLine("interface: " + testMethodViaInterface.Name);
            if (implementingMethod != null)
                Console.Out.WriteLine("class: " + implementingMethod.Name);
            else
                Console.Out.WriteLine("class: unable to locate"); 

            Console.Out.Write("Press enter to exit...");
            Console.In.ReadLine();
        }
    }

    public static class TypeExtensions
    {
        /// <summary>
        /// Gets the corresponding <see cref="MethodInfo"/> object for
        /// the method in a class that implements a specific method
        /// from an interface.
        /// </summary>
        /// <param name="interfaceMethod">
        /// The <see cref="MethodInfo"/> for the method to locate the
        /// implementation of.</param>
        /// <param name="classType">
        /// The <see cref="Type"/> of the class to find the implementing
        /// method for.
        /// </param>
        /// <returns>
        /// The <see cref="MethodInfo"/> of the method that implements
        /// <paramref name="interfaceMethod"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <para><paramref name="interfaceMethod"/> is <c>null</c>.</para>
        /// <para>- or -</para>
        /// <para><paramref name="classType"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <para><paramref name="interfaceMethod"/> is not defined in an interface.</para>
        /// </exception>
        public static MethodInfo GetImplementingMethod(this MethodInfo interfaceMethod, Type classType)
        {
            #region Parameter Validation

            if (Object.ReferenceEquals(null, interfaceMethod))
                throw new ArgumentNullException("interfaceMethod");
            if (Object.ReferenceEquals(null, classType))
                throw new ArgumentNullException("classType");
            if (!interfaceMethod.DeclaringType.IsInterface)
                throw new ArgumentException("interfaceMethod", "interfaceMethod is not defined by an interface");

            #endregion

            InterfaceMapping map = classType.GetInterfaceMap(interfaceMethod.DeclaringType);
            MethodInfo result = null;

            for (Int32 index = 0; index < map.InterfaceMethods.Length; index++)
            {
                if (map.InterfaceMethods[index] == interfaceMethod)
                    result = map.TargetMethods[index];
            }

            Debug.Assert(result != null, "Unable to locate MethodInfo for implementing method");

            return result;
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将从接口类型获取的 MethodInfo 对象转换为 C# 中实现类型上相应的 MethodInfo 对象? 的相关文章

  • C/C++ 中随机数生成器的实现[重复]

    这个问题在这里已经有答案了 我对 C 中随机数生成器的实现有点困惑 它也与 C 中的明显不同 如果我理解正确 对 srand seed 的调用会以某种方式初始化可通过 rand 访问的隐藏变量 种子 该变量又将函数指向预先生成的序列 例如例
  • 为什么 LinkedList 通常比 List 慢?

    我开始在我的一些 C 算法中使用一些 LinkedList 而不是列表 希望能够加快速度 然而 我注意到他们只是感觉更慢 像任何优秀的开发人员一样 我认为我应该尽职调查并验证我的感受 所以我决定对一些简单的循环进行基准测试 我认为用一些随机
  • 禁用除滚动之外的 DataGridView

    我如何配置 datagridview 以便用户只能在行中移动并使用滚动 而没有其他 如果我禁用网格不允许我使用滚动 将您的 datagridview 设置为只读 这将禁用任何编辑 dataGridView1 ReadOnly true 在你
  • TestMethod:异步任务 TestSth() 不适用于 .NET 4.0

    我正在尝试使用 NET 4 0 BCL Async 和 MsTest 运行异步测试方法 看来这个设置不能处理 测试方法 异步Task测试Sth 由于测试用例资源管理器中缺少条目 将签名更改为异步后void 我可以运行测试用例 但结果错误 根
  • initializer_list 和默认构造函数重载决策

    include
  • Type_traits *_v 变量模板实用程序顺序无法编译

    看过了这个答案 https stackoverflow com a 31763111 7151494 我试图想出一个变量模板从中获取代码的实用程序 template
  • 使用正则表达式匹配以“Id”结尾的单词?

    如何组合一个正则表达式来匹配以 Id 结尾的单词并进行区分大小写的匹配 试试这个正则表达式 w Id b w 允许前面的单词字符Id和 b确保Id位于单词末尾 b是字边界断言
  • 使用 Microsoft Graph 创建用户

    如何使用 Microsoft graph 创建用户 因为我在保存过程中遇到了权限失败的问题 我确实有几个问题 在图中调用创建用户 API 将在哪里创建用户 是在 Azure AD 还是其他地方 我尝试通过传递 json 和必需的标头来调用创
  • C++ 析构函数:何时释放内存?

    如果我删除一个导致其析构函数被调用的对象 那么内存是在析构函数完成函数中的任何操作之前还是之后被释放 仅当最小派生类子对象被销毁后才会释放内存 所以如果你有 class Base class Derived public Base publ
  • 基于 C++ 范围的 for 循环

    尝试使用基于范围的 for 循环执行某些操作 可以使用常规的 for 循环来完成 如下所示 vector
  • 使用 cudamalloc()。为什么是双指针?

    我目前正在浏览有关的教程示例http code google com p stanford cs193g sp2010 http code google com p stanford cs193g sp2010 学习CUDA 演示的代码 g
  • IEnumerable.比带中断的 for 循环更快吗?

    我们的代码打开表单时遇到了一些缓慢的情况 这可能是由于for循环与break这需要很长时间才能执行 我把它切换到IEnumerable Any 并看到表格很快打开 我现在试图弄清楚是否单独进行此更改会提高性能 或者是否正在访问Product
  • .NET 的 HttpWebResponse 是否会自动解压缩 GZiped 和 Deflated 响应?

    我正在尝试执行一个接受压缩响应的请求 var request HttpWebRequest HttpWebRequest Create requestUri request Headers Add HttpRequestHeader Acc
  • C# - 命名空间内的类型声明

    在命名空间内而不是在类中声明类型的可能用途是什么 For ex namespace Test public delegate void Ispossible 这是有效的并且不会产生任何编译错误 但我无法想象为什么我们会以这种方式声明它而不是
  • Unity 2.0 和处理 IDisposable 类型(特别是使用 PerThreadLifetimeManager)

    我知道类似的问题被问过好几次 例如 here https stackoverflow com questions 987761 how do you reconcile idisposable and ioc here https stac
  • printf 参数不足

    我的问题是关于缺少参数的 printf 之后的行为 printf s blah blah d int integer was given as argument and not int written 我已经知道 如果格式参数不足 则行为是
  • C 中的静态和动态绑定(严格来说是 C,而不是 C++)是什么?

    我最初对发布这个问题感到担忧 以免它重复 但即使在谷歌搜索了许多关键字之后 我在 StackOverflow 上找不到任何解释 C 的静态和动态绑定的链接 尽管有 C 的问题和答案 但是都涉及classes以及显然不适合 C 的东西 Sta
  • 计算两个日期之间的工作日数?

    在C 中 如何计算business 或工作日 两个日期之间的天数 我以前曾经遇到过这样的任务 并且我已经找到了解决方案 当可以避免的时候 我会避免列举其间的所有日子 这里就是这种情况 正如我在上面的一个答案中看到的那样 我什至没有提到创建一
  • 请解释为什么Java和C对此代码给出不同的答案

    public class Test public static void main String args int i 10 i i System out println value of i is i 输出是 10 当我在中执行类似的代码
  • 如何获取通过网络驱动器访问的文件的 UNC 路径?

    我正在 VC 中开发一个应用程序 其中网络驱动器用于访问文件 驱动器由用户手动分配 然后在应用程序中选择驱动器 这会导致驱动器并不总是映射到相同的服务器 我该如何获取此类文件的 UNC 路径 这主要是为了识别目的 这是我用来将普通路径转换为

随机推荐