gpt4 book ai didi

plugins - MEF 和版本控制

转载 作者:行者123 更新时间:2023-12-04 10:19:10 26 4
gpt4 key购买 nike

我正在考虑使用 MEF 来解决插件管理要求。在简介中它说“没有硬依赖”,但据我所知,对导入/导出接口(interface)存在硬依赖。

我关心的是这个。我的可扩展应用程序是由我编写的。插件由第三方编写。因此,假设我们都从 V1 开始。我的应用程序定义了 IPlugin插件“部件”需要实现的接口(interface)。我们部署应用程序,用户安装一堆第三方插件。一切都很好。

现在我升级了我的应用程序,我想在插件界面中添加一个新方法。我看到它的方式有两个选择:

  • 编辑接口(interface) - 可能不好,这会破坏现有插件,因为它们将不再正确实现接口(interface)。
  • 创建一个新的“V2”接口(interface),继承自原始接口(interface)

    公共(public)接口(interface) IPluginV2 : IPlugin {}

  • 现在我有一个问题。我的用户都有一堆实现 IPlugin 的第三方插件,但我现在要求他们实现 IPluginV2。我认为这些 3rd 方插件将不再工作,直到开发人员实现新接口(interface)。

    MEF 有办法处理这种情况吗?我真的在寻找一种方法,让我在改进我的应用程序的同时让旧插件继续工作而无需重新构建。最好的处理方法是什么?

    最佳答案

    对于版本控制,您可能需要每个版本的接口(interface)和 adapter pattern去他们之间。是这样的System.AddIn处理版本控制,它也适用于 MEF。

    假设我们有以下类型的 V1 您的应用程序:

    public interface IPlugin
    {
    string Name { get; }
    string Publisher { get; }
    string Version { get; }

    void Init();
    }

    这是我们 的唯一契约(Contract)。 V1 插件感知应用。它包含在程序集中 Contracts.v1 .

    然后我们有一个 V1 插入:
    [Export(typeof(IPlugin))]
    public class SomePlugin : IPlugin
    {
    public string Name { get { return "Some Plugin"; } }

    public string Publisher { get { return "Publisher A"; } }

    public string Version { get { return "1.0.0.0"; } }

    public void Init() { }

    public override string ToString()
    {
    return string.Format("{0} v.{1} from {2}", Name, Version, Publisher);
    }
    }

    导出为 IPlugin .它包含在程序集中 Plugin.v1并发布在主机应用程序基本路径下的“插件”文件夹中。

    最后是 V1 主持人:
    class Host : IDisposable
    {
    CompositionContainer _container;

    [ImportMany(typeof(IPlugin))]
    public IEnumerable<IPlugin> Plugins { get; private set; }

    public Host()
    {
    var catalog = new DirectoryCatalog("plugins");
    _container = new CompositionContainer(catalog);
    _container.ComposeParts(this);
    }

    public void Dispose() { _container.Dispose(); }
    }

    全部导入 IPlugin在文件夹“插件”中找到的部件。

    然后我们决定发布 V2 因为我们想要提供版本控制,所以我们需要无版本合约:
    public interface IPluginV2
    {
    string Name { get; }
    string Publisher { get; }
    string Version { get; }
    string Description { get; }

    void Init(IHost host);
    }

    具有新属性和修改的方法签名。另外,我们为主机添加了一个接口(interface):
    public interface IHost
    {
    //Here we can add something useful for a plugin.
    }

    这两个都包含在程序集中 Contracts.v2 .

    为了允许版本控制,我们添加了一个从 V1 到 V2 的插件适配器:
    class V1toV2PluginAdapter : IPluginV2
    {
    IPlugin _plugin;

    public string Name { get { return _plugin.Name; } }

    public string Publisher { get { return _plugin.Publisher; } }

    public string Version { get { return _plugin.Version; } }

    public string Description { get { return "No description"; } }

    public V1toV2PluginAdapter(IPlugin plugin)
    {
    if (plugin == null) throw new ArgumentNullException("plugin");
    _plugin = plugin;
    }

    public void Init(IHost host) { plugin.Init(); }

    public override string ToString() { return _plugin.ToString(); }
    }

    这只是改编自 IPluginIPluginV2 .它返回一个固定的描述并在 Init它对主机参数没有任何作用,但它调用无参数 Init来自 V1 契约(Contract)。

    最后是 V2 主持人:
    class HostV2WithVersioning : IHost, IDisposable
    {
    CompositionContainer _container;

    [ImportMany(typeof(IPluginV2))]
    IEnumerable<IPluginV2> _pluginsV2;

    [ImportMany(typeof(IPlugin))]
    IEnumerable<IPlugin> _pluginsV1;

    public IEnumerable<IPluginV2> Plugins
    {
    get
    {
    return _pluginsV1.Select(p1 => new V1toV2PluginAdapter(p1)).Concat(_pluginsV2);
    }
    }

    public HostV2WithVersioning()
    {
    var catalog = new DirectoryCatalog("plugins");
    _container = new CompositionContainer(catalog);
    _container.ComposeParts(this);
    }

    public void Dispose() { _container.Dispose(); }
    }

    这两个都导入 IPluginIPluginV2零件,适应每个 IPlugin进入 IPluginV2并公开所有已发现插件的串联序列。适配完成后,所有插件都可以视为 V2 插件。

    您也可以在主机的接口(interface)上使用适配器模式来允许 V2 使用的插件 V1 主机。

    另一种方法是 autofac可以 integrate 的 IoC使用 MEF 并且可以支持使用 adapters 进行版本控制.

    关于plugins - MEF 和版本控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15058797/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com