【问题标题】:Get the full name of a referenced type without loading its assembly在不加载其程序集的情况下获取引用类型的全名
【发布时间】:2020-10-28 00:55:42
【问题描述】:

我有一个 .Net 项目,其中给了我一个程序集 (*.dll),我必须列出包含的类型及其成员。但是,我没有得到程序集的引用。

假设给我A.dll,其中有一个类型:

public class TypeInA : IInterfaceInB
{
    ...
}

由于没有给我 B,所以当我尝试调用时,我会收到 FileNotFoundException

typeof(TypeInA).GetInterfaces()

因为它找不到B.dll

我不需要关于IInterfaceInB 的详细信息,只需要它的命名空间限定名称。有没有一种方法可以让我无需加载B.dll

更多上下文

我正在关注MetadataLoadContext docs 加载A.dll 并枚举其类型:

var runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");
var paths = new List<string>(runtimeAssemblies) {path};
var resolver = new PathAssemblyResolver(paths);
using var context = new MetadataLoadContext(resolver);

var assembly = context.LoadFromAssemblyPath(path);

【问题讨论】:

  • 你想知道柜子里有什么,但又不想打开柜子。你需要重新考虑你的问题。如果你真的需要这样做,我不知道为什么。将其存储在元数据文件中,或解析 IL
  • TypeInA 已经引用了IInterfaceInB。我只想知道它的名字。参考是什么样的?它不包含类型名称吗?
  • 我有点困惑,所以你有一个引用另一个不存在的程序集的程序集,你只是想找到你的程序集中存在的类型的完全限定名称没有?
  • 不一定“不存在”只是“没有”,但是是的。
  • typeof(TypeInA).Name 不起作用?

标签: c# reflection


【解决方案1】:

由您发布的Docs 提供

这个集合,除了你想直接检查的程序集外,还应该包括所有需要的依赖项。例如,要读取位于外部程序集中的自定义属性,您应该包含该程序集,否则将引发异常。

由于您没有B.dll,我认为当您尝试访问该程序集中的任何信息时它抛出异常是正常的。

但是,当我在 A.dll 上使用 ildasm.exe 时,我可以很容易地看到实现的接口的名称。所以至少应该可以得到名字。

有一个名为dnlib 的反编译库,我偶尔会用到它。这是一个示例代码,您可以在没有 B.dll 的情况下读取 A.dll 并获取 Types 实现的接口 FullName。

using System;
using System.Linq;
using dnlib.DotNet;
......
......
private static void Main(string[] args) {
    // You need a module context in order to load an assembly
    var moduleContext = ModuleDef.CreateModuleContext();
    // This is the loaded module, please take note that it not loaded into your Domain
    var loadedModule = ModuleDefMD.Load(@"A.dll", moduleContext);
    var classes = loadedModule
        .GetTypes() //You want types in this assembly
         // I think you need classes, (structs too maybe?)
         // But you do not need the Module
        .Where(t=>t.IsClass && t.IsGlobalModuleType == false);

    foreach (var typeDef in classes) {
        Console.WriteLine($"{typeDef.FullName} implements:");
        foreach (var typeDefInterface in typeDef.Interfaces) {
            Console.WriteLine($"  {typeDefInterface.Interface.FullName}");
        }
    }
    Console.ReadKey();
}

【讨论】:

    猜你喜欢
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 2012-05-13
    • 1970-01-01
    相关资源
    最近更新 更多