【发布时间】:2013-03-11 22:38:11
【问题描述】:
我目前正在从头开始设计一个系统,我们遇到了一个架构设计方案,我不确定最好的解决方法 - 但我相信其他人已经解决了,而且可能有甚至是它的模式。
到目前为止的故事:
我们有一个多租户网站,我们在其中实现各种功能作为插件,我们的客户将选择他们希望在他们的应用程序中使用的插件。每个插件都可以有各种用户可以添加到页面的“小部件”。 (例如,类似于 Android 应用程序通常带有可以添加到主屏幕的小部件的想法)。
插件可以依赖于其他插件来启用(例如电子商务插件需要支付插件)。插件也可以使用其他插件来增强其功能(例如,博客插件可以选择使用评论插件,也可以将评论与电子商务产品一起使用)。
尽可能地,我们希望每个插件都是独立的,具有非常简洁的公共接口。我们相信这种关注点分离将为我们提供整个系统的最佳长期灵活性和可维护性。
问题:
当我们开始布局我们目前知道的所有插件(更不用说未来的需求),以及它们与其他插件的依赖关系和可能的关系时 - 它开始与疯狂的蜘蛛网非常相似。我们也开始看到一些循环引用发生。
例如,导航插件需要知道网站上有哪些页面。但您也可以将导航小部件添加到页面。
部分/潜在的解决方案:
我们认为每个插件都应该与其他插件完全分开,但会通过消息从其他插件获取信息并与之通信。这些消息可以分为两种基本类型
- 从另一个插件请求信息(请求/响应消息)
- 事件通知(事件消息)
这两种消息类型都是非常简单的 DTO 类型类 - 它们不应该包含任何业务逻辑 - 只是一些其他服务处理请求并提供响应所需的信息。
我已经模拟了几个插件的一个非常简化的版本,我们看到它们与其他插件交互的解决方案是:http://screencast.com/t/Mdb9wUmMF
在此图中,Navigation、Page、Search 和 Other 插件不会相互了解任何信息。但他们会知道可用的消息和 ProcessMessages 接口。
例如请求/响应消息
Navigation 和其他插件会知道,如果它向 ProcessMessages 发送 GetPagesRequest,它将返回一个 PagesResponse,其中包含他们需要的所有信息。 (Nav/Other 插件需要立即响应 GetPagesRequest。)
导航和其他插件对页面插件一无所知。
请求/响应消息要求
引发请求消息的插件总是(通常?)期望立即收到响应消息。
只有 1 个服务知道如何处理请求消息,并提供将传递回调用插件的响应消息。
例如事件消息
当用户在页面插件中更新页面的 url 时,插件会向 ProcessMessages 发送 PageUrlUpdated 消息。 Navigation 和 Other 插件将使用 PageUrlUpdated 消息并执行它需要的任何操作。
事件消息要求
引发事件的插件从不期待响应。 0-许多插件可能会使用给定的消息。
(技术说明:对于事件消息,我们将把它们发送到 MassTransit 和 RabbitMQ - 然后每条消息有 1-n 个消费者)
问题
从我们制作的一些草图来看,上述想法似乎可行,并且系统不同元素之间的相互依赖性要少得多。但我不知道设计模式或架构结构的名称——或者我是否走错了路。我希望有人能给我指出正确的解决方案——一些好的文档和例子会很棒。 (尽量避免重新发明轮子 - 现有模式可能会更加稳健和成功)
对于请求消息,我们设想了某种从请求消息到将处理该消息的具体插件/服务的 StructureMap 映射。再说一次 - 我确信这个问题之前已经解决了,并且有一个模式,或者我们完全走错了路,有更好的解决方案。
非常感谢任何帮助和想法 萨安
PS - 我也会在一个具有一些基本属性的公共项目中拥有一个 IWidget - 所以页面插件可以请求所有实现 IWidget 的类添加到页面中
【问题讨论】:
-
听起来 MEF 是一个不错的起点——看看msdn.microsoft.com/en-us/library/dd460648.aspx
-
托管可扩展性框架足够强大,可以处理这种架构。本质上,插件会改变您的默认策略。 MEF 还提供属性和构造函数注入,因此您可以实例化一个插件并注入另一个插件。
-
分而治之。针对特定问题提出更小、更明确的问题,例如
how can I allow non-related classes consume information frome each others或how can a plugin invoke another plugin without create hard coupling between the plugins。 -
对于其他查看此问题的人。我最终发现上面的问题和图表描述了中介者模式。
标签: c# design-patterns plugins architecture