【问题标题】:Load an assembly without locking file AND keep the right Binding Context在不锁定文件的情况下加载程序集并保留正确的绑定上下文
【发布时间】:2011-07-13 03:10:48
【问题描述】:

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

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

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 绑定上下文中,而包含用于类型转换的类型的程序集(在我的例子中是MyApp. dll) 在默认上下文中加载。因此,即使它们具有相同的名称,它们也不被视为同一类型。这样做是因为我使用的是Assembly.Load(byte[])

问题

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

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

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

【问题讨论】:

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


    【解决方案1】:

    你试过shadow copying吗?

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

    【讨论】:

    • 好电话,最终我实现了这个,因为它看起来更优雅 - 而且它确实有效 - 所以重点是你。然而,当我开始在单独的应用程序域中实现加载插件时,我遇到了跨域通信的问题。我在域中传递的所有内容都必须从 MarshalByRefObject 继承才能正常工作,并且变得一团糟。不过,我正在研究 MEF,它看起来比构建我自己的本土产品更简单。
    【解决方案2】:

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

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

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

    只是一个想法。

    【讨论】:

    • +1。这允许您查看文件系统更新的“drop”目录,并轻松回收和刷新您的插件 AppDomain(s)。
    • 这是一个有趣的想法!我正在考虑将它们复制到 Path.GetTempPath() 中的临时目录。如果我这样做了,有没有办法使用 Assembly.LoadFrom() 以外的东西来加载它们?使用该方法为我提供了 LoadFrom 绑定上下文,这似乎有很多缺点。
    • 是的,您可以使用Assembly.Load()。看看这个:stackoverflow.com/questions/2886397/… Btw,你看过 MEF 吗?
    • 我以前没有……但我越深入研究它,就越觉得这是要走的路。我似乎在重新发明轮子,他们已经创建了一个使用插件的框架。
    • 您确实是在重新发明轮子,但是这样做意味着:1,您不依赖于 MEF;2,您将在此过程中学到很多东西。自己动手做总是很有趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-13
    • 2011-03-27
    • 2019-02-07
    • 2012-08-30
    • 1970-01-01
    相关资源
    最近更新 更多