.net自动装配解决加载重复装配

时间:2017-02-28 18:16:02

标签: c# .net-assembly appdomain

我有一个依赖于库的可执行文件。我还有一个“加载器”应用程序,它将可执行文件加载到一个单独的AppDomain(我的“沙箱”)并在那里运行它。库需要从沙箱外部进行初始化,因此我需要在加载可执行文件之前加载库。这可以按预期工作,但是当我现在加载可执行文件时,库会再次加载,并且可执行文件使用未初始化的副本。

只有当我像这样加载库时才会出现这种情况:

 Assembly.Load(File.ReadAllBytes(assemblyFile.FullName));

而不是:

Assembly.LoadFrom(assemblyFile.FullName);

但是,使用LoadFrom会锁定文件。我需要能够删除/写入文件,因为我的应用程序需要能够重新加载整个沙箱及其中的所有程序集。

我也尝试过注册AppDomain.AssemblyResolve,但只有在找不到文件时才调用它,这不是我想要的......

示例日志输出:

  • 加载库X< - 手动加载
  • 初始化库X
  • 正在加载可执行文件
  • 加载库X< - 不好,我想使用加载的X!

所以我的问题是:如何强制.net使用已加载的程序集而不是加载副本?

2 个答案:

答案 0 :(得分:3)

我最终修改了沙盒的AppDomainSetup:

domainSetup.DisallowApplicationBaseProbing = true;

现在,每次都会调用AssemblyResolve(没有程序集的自动发现)。现在我可以从byte []加载程序集并缓存它们(感谢@DanField建议缓存程序集)

答案 1 :(得分:2)

来自remarks on Assembly.Load(Byte[])

  

请注意,此方法重载始终会创建一个具有自己的映射的新Assembly对象。

如果你想重用你加载的程序集,你不能使用那个重载(无论如何没有额外的工作 - 框架不会自动为你做这件事。)

您可以在此处使用Assembly.Load(string)Type.GetType(string)方法,但我怀疑仍然会锁定您要修改的文件。我不确定如何理解在运行时修改这些文件是否诚实 - 如果删除或更改已加载的程序集,预期的行为是什么?重新加载吗?修改后的代码是否已输入内存?

您可能需要创建自己的某种汇编缓存机制。如果程序集不是很大并且你可以将它们保存在内存中,它可能就像Dictionary<string, Assembly>一样简单 - 只需在加载之前检查字典是否包含程序集,否则使用{加载它} {1}}你现在的样子。