如何在 C# 中运行时加载程序集及其所有依赖项以进行反射?
-
09-06-2019 - |
题
我正在为自己编写一个实用程序,部分是作为学习 C# 反射的练习,部分是因为我实际上想要生成的工具供我自己使用。
我所追求的基本上是将应用程序指向程序集并选择给定的类,从中选择应作为字段包含在导出的 HTML 表单中的属性。然后,该表单将在我的 ASP.NET MVC 应用程序中用作视图的开头。
由于我在想要使用的应用程序中使用 Subsonic 对象,因此这应该是合理的,并且我认为,通过想要根据数据类型包含不同的输出 HTML 之类的内容,反射是完成此操作的方法。
然而,我正在寻找的东西似乎难以捉摸。我试图将通过 OpenFileDialog 选择的 DLL/EXE 作为起点并加载它:
String FilePath = Path.GetDirectoryName(FileName);
System.Reflection.Assembly o = System.Reflection.Assembly.LoadFile(FileName);
这工作正常,但由于 Subsonic 生成的对象实际上充满了 Subsonic.dll 等中定义的对象类型,因此不会加载这些依赖对象。进入:
AssemblyName[] ReferencedAssemblies = o.GetReferencedAssemblies();
这也正是我所期望的。然而,我想要弄清楚的是如何加载这些程序集,以便我对对象的挖掘能够正常工作。据我所知,如果这些程序集位于 GAC 中或正在运行的可执行文件的目录中,我可以通过它们的名称加载它们,但对于此用例来说,情况不太可能是这样,这是我的主要用例。
因此,归根结底就是如何加载给定的程序集及其以文件名开头的所有任意程序集,并生成完全可反射浏览的类型、属性、方法等树。
我知道像 Reflector 这样的工具可以做到这一点,但我只是找不到实现它的语法。
解决方案
这里有几个选项:
- 附加到
AppDomain.AssemblyResolve
并做另一个LoadFile
根据要求的装配。 - 旋转另一个
AppDomain
以目录为基础并加载其中的程序集AppDomain
.
我强烈建议采用选项 2,因为这可能会更干净,并且允许您在之后卸载所有这些程序集。另外,如果您只需要反射程序集,请考虑在仅反射上下文中加载程序集(请参阅 Assembly.ReflectionOnlyLoad
).
不隶属于 StackOverflow