代码之家  ›  专栏  ›  技术社区  ›  Marc Climent

扩展/插件通信体系结构

  •  5
  • Marc Climent  · 技术社区  · 15 年前

    一旦加载插件的问题得到解决(在.NET中,通过mef-in-out的情况),下一步要解决的是与插件的通信。简单的方法是实现一个接口并使用插件实现,但有时插件只需要扩展应用程序的工作方式,可能会有很多扩展点。

    我的问题是如何处理这些扩展点。我看到过不同的方法,但我不确定每种方法的优缺点,如果有更多更好的方法来实现这一点:

    • 事件:将静态事件添加到我们希望使“可扩展”的所有内容中。例如,如果我想为用户类添加自定义验证,我可以添加一个onvalidation静态事件处理程序,并在构建插件时从该插件向其添加事件。
    • 信息传递:有总线和信息。插件可以订阅特定的消息,并在其他类发布该消息时进行处理。消息应该包含插件可以在其中工作的上下文。在验证案例中,逻辑层将发布一条用户验证消息,插件将在收到消息时执行操作。
    • 接口:宿主应用程序负责调用实现某些接口的所有插件,并为它们提供当前操作的上下文。在验证的情况下,插件可以使用validate(对象上下文)方法实现IValidator或IUservalidator。

    您是否曾经使用过其中一种公开的方法?哪一个最适合你?

    在您询问之前,我们的应用程序是一个可扩展的核心(用户、ROL和内容管理),可以在此基础上构建特定于客户机的以内容为中心的Web应用程序。一切都建立在ASP.NET MVC之上。

    2 回复  |  直到 15 年前
        1
  •  2
  •   sharkin    15 年前

    您的设计决策的关键是分析并清楚地了解插件与其他插件的区别。

    例如,在处理静态事件时,您可能必须将每个事件定义为某种形式的令牌、枚举、对象等。必须为每个插件定义一组新的事件,这自然会对您的整个设计产生不利影响,特别是在松散耦合和重用方面。

    如果您的插件非常不同,您可能会受益于具有总线/消息传递体系结构,因为在这种情况下,您可以引入通信交换的域/类别,插件可以订阅这些域/类别。也就是说,一系列事件和消息可以在某个感兴趣的域中。请注意,在某个类别中的通信仍然可以使用静态事件,因此这两个备选方案并不相互排斥。

    根据我的经验,插件实现的直接接口是插件体系结构中最严格的方法。扩展插件接口通常意味着同时修改插件和提供程序的代码。您需要有一个可靠的通用接口,您知道您的应用程序可以在这个接口上生存一段时间。

    通过将设计分为两个方面,您可能更容易处理它- 通信信道 协议 . 静态事件处理是一个协议问题,而总线消息和直接接口是一个通道问题。

    通常我会说,从一开始就很难正确地设计协议,因为您可能对您可以画线的一般性或具体性没有明确的感觉。

    编辑: Lars在他的评论中提出了一个重要的观点——如果你的平台支持异常,你可以在使用直接接口时集中大量的错误处理,从而使插件不必处理一般性的错误,可能会超出它们的特定域(例如“插件加载错误”或“文件打开失败”)。但是,如果每次添加插件时都必须维护接口,那么这样的好处似乎就会消失。最糟糕的情况是,当界面开始变得不一致时,因为您没有意识到它们从一开始就应该支持什么。当已经构思了大量插件时,重构整个接口设计不是一件容易的任务。

        2
  •  0
  •   Martin    15 年前

    我愿意和你一起去 观察员 模式。来自GOF:

    定义一对多依赖项 在对象之间,以便 对象更改其所有状态 家属会得到通知和更新 自动地。

    也被称为publish subscribe,我建议它与您示例中的情况2最接近。