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

时间:2011-03-10 23:16:31

标签: c# .net plugins assemblies assembly-loading

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

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

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

MyPlugin.dll
|_MyPlugin.cs (this extends PluginBase)
|_Foo.cs

问题

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

byte[] readAllBytes = File.ReadAllBytes("MyPlugin.dll");
Assembly assembly = Assembly.Load(readAllBytes);

加载插件程序集工作正常,没有问题。从插件程序集中的 MyPlugin.cs 中,我尝试使用HelperCollection进行反序列化时出现异常。一个例子可能是这样的:

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

它正在爆炸并抛出一个InvalidCastException说它是"Unable to cast object of type 'List[Foo]' to 'List[Foo]'"。经过大量研究I finally found why。它已加载到LoadNeither binding context

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

问题

我该如何解决这个问题?我怎么能,

  1. 加载程序集而不是锁定文件,
  2. 提供正确的绑定上下文,以便我可以转换位于已加载程序集中的对象。
  3. 对于文字墙感到抱歉,只是想获得所有相关信息。

2 个答案:

答案 0 :(得分:6)

您是否尝试过shadow copying

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

答案 1 :(得分:2)

从我的头脑中只是一个想法:

如果有一个Plugin目录,用户可以将其插件插入其中。然后在您的应用程序中,您监视该文件夹并程序集复制到bin或其他任何内容。 然后你以“正常”方式加载它们,这可能会锁定它们。

当用户删除新插件时,您将终止插件应用程序域并重新加载它们。

只是一个想法。