如何通过System.Reflection.Metadata获取接口实现类的接口完全限定名
解决方案
要解析interfaceImplementation.Interface对应的接口完全限定名,需要根据它的句柄类型(当前程序集定义的接口用TypeDefinitionHandle,引用程序集的接口用TypeReferenceHandle)分别处理,以下是具体实现:
核心逻辑步骤
- 判断
interfaceImplementation.Interface的句柄类型:- 如果是
TypeDefinitionHandle:直接读取当前程序集内的接口定义,获取命名空间和类型名。 - 如果是
TypeReferenceHandle:读取引用类型的元数据,解析其命名空间和类型名。
- 如果是
- 将命名空间与类型名拼接成
[命名空间].[类型名]格式的完全限定名,即可与目标接口名称对比。
修改后的完整代码
namespace ReflectionMetadataTest { using System; using System.IO; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; public static class Program { // 定义要查找的目标接口完全限定名,比如 "System.IDisposable" private const string TargetInterfaceFullName = "System.IDisposable"; static int Main(string[] args) { if (args.Length < 1) { Console.Error.WriteLine("Please specify a single file path."); return 1; } string filePath = new FileInfo(args[0]).FullName; using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var peReader = new PEReader(fileStream)) { if (!peReader.HasMetadata) { return 2; } MetadataReader metadataReader = peReader.GetMetadataReader(); foreach (var typeDefinitionHandle in metadataReader.TypeDefinitions) { var typeDefinition = metadataReader.GetTypeDefinition(typeDefinitionHandle); var interfaceHandles = typeDefinition.GetInterfaceImplementations(); foreach (var interfaceHandle in interfaceHandles) { var interfaceImplementation = metadataReader.GetInterfaceImplementation(interfaceHandle); var interfaceTypeHandle = interfaceImplementation.Interface; // 解析接口的完全限定名 string interfaceFullName = GetFullTypeName(metadataReader, interfaceTypeHandle); // 与目标接口名称对比 if (string.Equals(interfaceFullName, TargetInterfaceFullName, StringComparison.Ordinal)) { // 获取当前实现类的完全限定名 string implementingTypeFullName = GetFullTypeName(metadataReader, typeDefinitionHandle); Console.WriteLine($"找到实现目标接口的类:{implementingTypeFullName}"); } } } return 0; } } } // 通用方法:根据类型句柄获取完全限定名 private static string GetFullTypeName(MetadataReader reader, EntityHandle typeHandle) { return typeHandle switch { TypeDefinitionHandle defHandle => $"{reader.GetString(reader.GetTypeDefinition(defHandle).Namespace)}.{reader.GetString(reader.GetTypeDefinition(defHandle).Name)}", TypeReferenceHandle refHandle => $"{reader.GetString(reader.GetTypeReference(refHandle).Namespace)}.{reader.GetString(reader.GetTypeReference(refHandle).Name)}", // 处理特殊情况:类型规范(比如泛型实例),如需更复杂场景可扩展 TypeSpecificationHandle specHandle => reader.GetString(reader.GetTypeSpecification(specHandle).TypeSignature.GetSignatureType().GetName(reader)), _ => throw new NotSupportedException($"不支持的类型句柄:{typeHandle.Kind}") }; } } }
关键说明
GetFullTypeName是通用方法,能处理三种常见的类型句柄,覆盖当前程序集、引用程序集以及泛型接口的情况。- 对比时使用
StringComparison.Ordinal避免文化差异导致的匹配错误,符合.NET类型名称的匹配规则。 - 无需加载任何引用程序集,完全通过元数据读取实现判断,满足你的场景需求。
内容的提问来源于stack exchange,提问作者ackh
相关产品推荐
相关产品推荐

