如何在AssemblyResolve事件之前在运行时加载程序集?

实际上我试图在我的解决方案中实现某种“静态链接”程序集。 所以我尝试了以下内容:

  • 使用CopyLocal = false添加对程序集的引用
  • 使用“添加为链接”将.dll文件本身添加到我的解决方案中
  • 使用“添加资源”将“.dll”文件本身添加到我的资源中 – “添加现有文件”
  • 将我的程序集中的某些类型添加到Form1中作为private MyObject temp = new MyObject();

执行这些步骤后,我按预期获得了FileNotFoundException。 因此,让我们尝试使用此快速入侵在AssemblyResolveEvent中加载程序集

 AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => { Assembly MyAssembly = AppDomain.CurrentDomain.Load(Properties.Resources.ExternalAssembly); return MyAssembly; }; 

这样可行! 我可以从AssemblyResolveEvent中的资源文件加载我的程序集。 但是这个事件只会发生,如果它无法在其他任何地方找到我的组件。 但是我怎么能 .Net尝试搜索不同的地方之前加载我的程序集?

由于检查先前引用的程序集的事实,我认为可以预先将程序集加载到域中,这将被采用。

我在program.cs中使用以下Main()方法尝试了这个

 static void Main() { LoadMyAssemblies(); AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => LoadMyAssemblies(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } private static Assembly LoadMyAssemblies() { Assembly result = AppDomain.CurrentDomain.Load(Properties.Resources.MyStaticAssembly); return result; } 

但它仍会运行到ResolveEventHandler中。 更好的是,如果我再次加载程序集并查看AppDomain.CurrentDomain.GetAssemblies()我可以看到我的程序集加载了两次!!

所以任何想法为什么我的装载程序集在AssemblyResolve事件之前加载时不会被考虑在内? 在调试器的帮助下,当调用来自AssemblyResolve时,我也返回了一个null,但是在这种情况下,我得到了一个FileNotFoundException。

如果您不知道,MS Research的工具名为ILMerge ,它将程序集合并到一个文件中。

您还可以使用“ 程序集链接器”工具创建多文件程序集。

另外回答你原来的问题,我认为问题是运行时不知道你手动加载的程序集应该是它应该寻找的程序集。 因此,在程序集解析事件中,而不是再次加载程序集,只需将引用传递回您手动加载的程序集。

CLR Binder不知道LoadMyAssemblies()与AssemblyResolve事件做同样的事情,并且他们都试图寻找相同的程序集并加载它。

AssemblyResolve事件总是在Binder决定它已经搜索了所有可能的位置(可以搜索该应用程序)并且找不到匹配的位置被触发。

这引出了原始问题,也就是说,为什么要静态链接托管程序集? 阅读此主题以获得有关此静态链接优势的大量讨论

我将继续回答关于如何避免遇到AssemblyResolve事件的部分1)将程序集放入GAC。 就Binder而言,GAC总是获胜。 2)将程序集放在探测路径中,并确保Binder选择它(在MSDN上查找文章“运行时如何定位程序集”以获取更多信息)。