加载程序集而不锁定文件并保留正确的绑定上下文

Oni*_*mus 7 .net c# plugins assemblies assembly-loading

我已经克服了一个令人生畏的难题.这是我的情况:

我正在使用插件框架构建应用程序.有一个基本插件类,所有插件都必须扩展.在同一个程序集中,我有一个帮助程序类,它将序列化和反序列化类.它是一个通用类,它遍布各处.结构是这样的:

MyApp.dll
|_ App.cs
|_ HelperCollection.cs
|_ PluginBase.cs

MyPlugin.dll
|_MyPlugin.cs (this extends PluginBase)
|_Foo.cs
Run Code Online (Sandbox Code Playgroud)

问题

我的问题是程序集加载和锁定文件.该应用程序的一个要求是可以随时覆盖插件.如果是这样,他们需要重新加载.这似乎是加载程序集以使其不被锁定的最佳方式(也就是说,我可以在应用程序仍在运行时覆盖它或吹走)是这样的:

byte[] readAllBytes = File.ReadAllBytes("MyPlugin.dll");
Assembly assembly = Assembly.Load(readAllBytes);
Run Code Online (Sandbox Code Playgroud)

加载插件组件工作正常,没有问题.我从插件程序集中的MyPlugin.cs中得到一个例外,我试图使用它HelperCollection进行反序列化.一个例子可能是这样的:

// HelperCollection uses XmlSerializer under the covers
List<Foo> settingCollection = HelperCollection<Foo>.Deserialize("mysettings.xml");
Run Code Online (Sandbox Code Playgroud)

它正在爆炸并抛出一个InvalidCastException说法"Unable to cast object of type 'List[Foo]' to 'List[Foo]'".经过多次研究,我终于找到了原因.它被加载到LoadNeither绑定上下文中.

何时Foo加载(来自MyPlugin.dll)它位于LoadNeither绑定上下文中,而包含类型转换类型的程序集(在我的情况下,MyApp.dll)在Default上下文中加载.因此即使它们具有相同的名称,它们也不被认为是相同的类型.这是因为我正在使用它Assembly.Load(byte[]).

问题

我怎么能绕过这个?我怎么能够,

  1. 加载程序集而不是锁定文件,和
  2. 提供正确的绑定上下文,以便我可以转换位于已加载程序集中的对象.

对不起文本墙,只是想获得所有相关信息.

Joe*_*ite 6

你试过影子复制吗?

当您使用卷影复制时,.NET会将程序集复制到临时目录并从那里加载它(因此它是锁定的临时文件,而不是原始程序集) - 但所有绑定规则都基于原始文件位置.