在C#中进行反射,如何在运行时加载程序集及其所有依赖项?

16

我正在为自己编写一个实用程序,一方面是为了学习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这样的工具可以实现这一点,我只是找不到使用语法。

2个回答

13

有几个选项:

  1. 附加到 AppDomain.AssemblyResolve 并基于请求的程序集执行另一个 LoadFile
  2. 创建具有该目录为基础的另一个 AppDomain 并在该 AppDomain 中加载程序集。

我强烈建议选择第二个选项,因为这样可能更加清晰,并允许您在之后卸载所有这些程序集。此外,如果你只需要反射它们,可以考虑在反射-only 上下文中加载程序集(参见 Assembly.ReflectionOnlyLoad)。


如何执行选项2? - Zoli

5
我解决了Kent Boogaart的第二个选项。 基本上,我需要做以下几点:
1.) 在单独的类中实现ResolveEventHandler,该类继承自MarshalByRefObject并添加Serializable属性。
2.) 将当前的ApplicationBase(事件处理程序的dll所在位置)添加到AppDomainPrivateBinPath中。
您可以在github上找到代码。

你说的是MarshalByValueObject。你是不是想说MarshalByRefObject? - Tengiz
哦,没错,MarshalByRefObject。 - mathume

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接