【问题标题】:Get .NET type from Mono.Cecil从 Mono.Cecil 获取 .NET 类型
【发布时间】:2020-10-25 23:32:28
【问题描述】:

我正在开发一个 .NET 应用程序。在我的应用程序中,我必须检查程序集中的类型是否实现了特定的接口。我的程序集有一个来自 NuGet 包(依赖项)的包,所以我使用 Mono.Cecil 来获取程序集中的所有类型。代码是:

ModuleDefinition module = ModuleDefinition.ReadModule(assemblyPath);
Collection<TypeDefinition> t1 = module.Types;

问题在于 Mono.Cecil 返回 TypeDefinition 而不是 Type。那么无论如何我可以将集合中的每个 TypeDefinition 转换为 .NET Type 以便我可以轻松检查该类型是否实现特定接口?

任何帮助将不胜感激。

【问题讨论】:

  • 是否有理由必须使用 Cecil 而不能直接使用 Assembly/Type 类? (即使用 Load/LoadFile 加载程序集,然后使用 GetTypes 等)
  • 是的,我的程序集中安装了一个 NuGet 包,在这种情况下,我不能使用简单的程序集/类型类。 @pinkfloydx33
  • 我不明白为什么不这样做。 Nuget 依赖项被复制到输出目录。如果您已经在该程序集中引用类型,那么它就像 typeof(SomethingInNuget).Assembly 一样简单,但否则路径将在您的程序集旁边,所以我很困惑
  • 程序集 = Assembly.Load(File.ReadAllBytes(assemblyPath)); foreach (在 assembly.GetExportedTypes()) 中键入 t{} 。 . . .在 foreach 我得到异常“无法加载文件或程序集'Quartz'。.@pinkfloydx33
  • 尝试使用带有程序集路径的 LoadFrom 或使用 AssemblyName 加载(如果您不知道 AssemblyName 的含义,请查看它,因为它并不完全符合人们的预期)。从字节数组加载似乎没有加载程序集的依赖项(如果没有自定义的 Assembly Resolve 事件知道在哪里看,这有点道理)

标签: c# mono.cecil


【解决方案1】:

如果你可以使用接口的全名,那么你不需要TypeTypeDefinition就足够了。示例(在 F# 中):

let myInterface = "Elastic.Apm.Api.ITracer"

let implementsInterface (t : Mono.Cecil.TypeDefinition) =
  t.HasInterfaces
  && t.Interfaces |> Seq.exists (fun i -> i.InterfaceType.FullName = myInterface)

let getTypes assemblyFileName =
  Mono.Cecil.AssemblyDefinition
    .ReadAssembly(fileName = assemblyFileName).MainModule.Types
  |> Seq.filter implementsInterface
  |> Seq.map (fun t -> t.FullName)
  |> Seq.toArray

let ts = getTypes assemblyFile
printfn "Types implementing %s: %A" myInterface ts
// Output:
// Types implementing Elastic.Apm.Api.ITracer: [|"Elastic.Apm.Api.Tracer"|]

【讨论】:

  • 我可以使用接口的全名,但我想要实现接口的程序集中的类型,因为我必须做一些需要类型的处理。
  • 你能通过反射加载那个程序集吗?如果是这样,您可以通过全名获取您的类型。 assembly.GetType("Your.Type.Full.Name")
猜你喜欢
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
  • 2016-11-26
  • 1970-01-01
  • 2022-11-09
  • 2014-08-02
  • 2011-05-07
  • 2015-12-20
相关资源
最近更新 更多