7

我已经解决了一个可怕的难题。这是我的情况:

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

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]'"。经过大量研究,我终于找到了原因。它正在LoadNeither 绑定上下文中加载。

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

问题

我怎样才能解决这个问题?我怎样才能,

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

对不起,文字墙,只是想把所有相关信息都放在那里。

4

2 回答 2

6

你试过影子复制吗?

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

于 2011-03-11T00:01:04.580 回答
2

只是我脑海中的一个想法:

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

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

只是一个想法。

于 2011-03-10T23:44:12.680 回答