【问题标题】:How to remove MEF plugins at runtime?如何在运行时删除 MEF 插件?
【发布时间】:2011-03-22 18:07:41
【问题描述】:

我有一个基于 MEF 的应用程序,可以使用插件进行自定义。这个应用程序有几个导入的部分,当用户决定摆脱该插件时,我想在运行时删除其中的一些(以便能够删除包含它们的 .dll)。

CompositionBatch 可以满足我的需要,但它需要ComposablePart 实例作为RemovePart() 方法的输入参数,而且我只有实现ISomething 接口的普通对象,或者AggregateCatalog 中的ComposablePartDefinition 实例。所以我的问题是:

  • 如何找到 ComposablePart 表示导入的实例 我想摆脱的对象?
  • 或 或者:我如何获取列表 属于的 ComposablePart 对象 到某个.dll?

我会使用如下内容:

var parts = Container.Catalog.Parts
           .Where(p => iDontNeed(p))
           .Select(p => howDoIConvertComposablePartDefinition2ComposablePart(p));
var batch = new CompositionBatch();
parts.ToList().ForEach(part => batch.RemovePart(part));

谢谢

【问题讨论】:

    标签: c# .net mef


    【解决方案1】:

    如何获取属于某个 .dll 的 ComposablePart 对象列表?

    要从特定组件中移除部件,您只需调用 AggregateCatalog.Catalogs.Remove 即可移除 AssemblyCatalog。不过,您必须设计您的零件以允许Recomposition

    但是,这不会帮助您删除插件程序集。该程序集仍将被加载,并且您无法在加载时更改或删除 .NET 程序集。 卸载程序集而不停止进程的唯一方法是卸载它加载的AppDomain。但是,如果您为插件引入单独的AppDomain,那么您基本上必须通过远程处理等方式与这些插件进行通信。

    停止应用程序、删除插件程序集并重新启动可能更简单、更安全、更有效。

    edit:实际上,一种方法可以在不停止进程或卸载整个应用程序域的情况下删除插件 dll 文件:您可以为应用程序启用 shadow copying -domain 指示 .NET 在加载程序集之前进行复制。副本将保持加载状态,但至少您可以删除或替换原始文件。

    【讨论】:

    • 如果未来 MEF 支持卸载程序集似乎会很好。我希望能够就地更新插件。重新启动应用程序不是一个可接受的折衷方案,而且我无法在不卸载程序集的情况下覆盖 DLL。所以我可能无法按原样使用 MEF。我得写点反思的东西。
    • @Josh G:我看不出使用反射编写自己的插件系统会如何解决任何问题。所描述的卸载问题不仅限于 MEF,这正是 .NET 的工作原理。
    • 我发现了这一点。我假设我可以卸载带有反射的程序集以及加载它。原来我将不得不使用 AppDomains。
    • 我最近编写了一个演示,其中包含有关如何执行此操作的源代码。 codeproject.com/Articles/633140/…
    【解决方案2】:

    MAF 能帮到您吗?我不是专家,但我知道使用 MAF,插件会保留在自己的进程中,并且可以在运行时卸载。我猜这不会在您进行跨进程通信时提供理想的性能,但如果这不是主要问题,那么可能值得一看。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      • 2014-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多