运行时程序集解析

3
我希望在我的应用程序中使用AssemblyResolver事件动态加载程序集,但我不知道该如何操作。
我看了这个教程并尝试了一下。 在第三条技巧中,他写道:
static void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
}
static void Print()
{
    var mainClass = new MainClass();
    mainClass.Print();
}

static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
{
    return Assembly.LoadFile(@"path to the library");
}

其实我不理解这段代码应该如何编译...

new MainClass()无法编译,因为它是未知的(类型尚未加载),加载发生在运行时。
如果MainClass是已知类型,则根本不需要解析...

这段代码应该如何运作?


我认为print是一种用于调试的方法(例如,调用堆栈),并不表示加载的程序集中包含的内容。作者应该在前几章中给出了代码。 - Lei Yang
2个回答

1
如果它能编译,那么很可能你已经引用了一个具有MainClass类型和Print方法的库,即使它只是一个空桩或错误的实现。这并不是“未知的”。如果它是未知的,那么这段代码就不能编译,你必须在运行时使用反射来查找类型,并使用反射来实例化实例,并使用反射来调用Print()方法(除非有一些众所周知的接口或基类可以转换,或者您使用dynamic)。
这就是编译所需的全部:元数据。事实上,针对“参考库”的目标是相当常见的 - 这正是您的IDE中许多多目标功能的工作原理。

在运行时,您可以重写加载以提供预期的库,但老实说,将实际库部署到应用程序的探针路径(通常为:主exe旁边)中通常更容易。此外,在您的ResolveAssembly方法中,检查请求的程序集是什么是个好主意 - 它可能正在尝试加载完全不相关的内容,在这种情况下,请不要管它。


但是如果我将空存根添加为项目的引用,当出现new MainClass()时,ResolveAssembly会被触发吗? - nrofis
@nrofis 当JIT需要时,它会发生,所以最晚new MainClass()运行时发生,但可能更早。 - Marc Gravell
即使MainClass已知并存在于引用中? - nrofis

0

如果你想加载一个你不知道内容的程序集(然后使用反射来实例化它的类),你可以简单地使用Assembly.Load(),如果你有它的全名(名称、版本、文化和公钥令牌,如果有的话),或者使用Assembly.LoadFrom,如果你有它的路径名。

AssemblyResolve用于“重定向”在编译时已知但在运行时必须从特定路径加载的程序集。你可以明确地使用它来“引诱并替换”程序集(在编译时你有一个程序集,在运行时你加载一个实现相同类的不同程序集)。


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