扩展/插件通信的架构

2024-02-19

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

我的问题是关于如何处理这些扩展点。我已经看到了不同的方法,但我不确定每种方法的优缺点,以及是否有更多更好的方法来实现这一目标:

  • 事件:将静态事件添加到我们想要“可扩展”的所有内容中。例如,如果我想为 User 类添加自定义验证,我可以添加 OnValidation 静态事件处理程序,并在构建插件时向其添加事件。
  • 消息传递:拥有总线和消息。该插件可以订阅特定消息,并在其他类发布该消息时执行某些操作。该消息应包含插件可以工作的上下文。在验证情况下,逻辑层将发布 UserValidation 消息,插件将在收到消息时采取行动。
  • 接口:主机应用程序负责调用所有实现某些接口的插件,并为它们提供当前操作的上下文。在验证的情况下,插件可以使用 Validate(object context) 方法实现 IValidator 或 IUserValidator。

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

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


设计决策的关键是分析并清楚地了解插件之间的差异。

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

如果您的插件非常不同,您可能会受益于总线/消息传递架构,因为在这种情况下您可以引入插件可以订阅的通信交换的域/类别。 IE。一系列事件和消息可以处于某个兴趣域中。请注意,特定类别内的通信仍然可以利用静态事件,因此这两种选择并不相互排斥。

根据我的经验,插件实现的直接接口是插件架构中最严格的方法。扩展插件接口通常意味着插件和提供者的代码修改。您需要有一个可靠的通用界面,您知道您的应用程序可以运行相当长的一段时间。

通过将设计分解为两个方面,您可能会更容易处理设计 -沟通渠道 and protocol。静态事件处理是一个协议问题,而总线消息传递和直接接口是一个通道问题。

一般来说,我会说协议是最难从一开始就正确设计的,因为您可能对如何划定界限没有明确的感觉。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

扩展/插件通信的架构 的相关文章

随机推荐

  • 带有 dotnet pack 的软件包版本始终为 1.0.0

    TLDR 在哪里dotnet pack在为程序集创建 nuget 包时提取版本信息 我有一个库 我已将其从 NET 4 6 1 项目转换为 NET Core 项目project json 对于我在此期间的 CI 使用 TFS 2015 vn
  • 如何在 Rails 5.1 中运行无头浏览器系统测试?

    The Rails 5 1 系统测试文档 http guides rubyonrails org testing html implementing a system test有点稀疏 我无法获得执行 javascript 运行的无头测试
  • 如何防止 SSRS 报告中的正文自动调整大小

    我有一份报告 其中的页眉和页脚都设置为填充整个 A4 长度 当然减去边距 因为我有一些关于它们的最右侧和最左侧的信息 现在 在正文中 我有一个列表元素 它允许我将 tablix 报告和图表放在一起 正文的大小也适当 以保持在报告的页码限制内
  • 经过几次乘法**有溢出**之后,是否有可能得到一个数字的原始值?

    概括 有没有办法做到这一点 这就是我的意思 假设我有一个无符号整数数字 然后我将其相乘几次 并且出现溢出 这是预期的 那么是否可以 恢复 原来的值呢 详细信息 这全都是关于Rabin Karp 滚动哈希 http en wikipedia
  • ParseUI 本地化

    由于 ParseUI 是开源的 因此很容易发现所有标签都在 ParseUI strings 中本地化 如何告诉 xcode 在运行时不要使用 ParseUI strings 而使用 Localisable strings 我在我的项目中创建
  • 尝试使用 Java 中的 Gmail API 发送电子邮件时出错

    我想使用 Gmail API 而不是 JavaMail 发送电子邮件 我在论坛上读到了很多类似的主题 但仍然有一个问题 首先我读到了这个 https developers google com gmail api guides sendin
  • 如何在XML中编写具有多个命名空间的xsd文件?

    当我在 mec xsd 中定义 XML 模式时 它不适用于该元素 我该如何解决这个问题 谢谢
  • 在 Eclipse CDT 中创建一个新的 C++ 项目,设置与另一个项目相同

    是否有一种简单的方法来创建克隆现有项目设置的新 C 项目 在开发 C 时 我喜欢编写许多小测试和示例 但如果我的代码依赖于外部库 就像它们经常做的那样 我必须每次都从头开始设置包含 库 编译器设置等 有某种模板机制吗 我了解 C C 项目设
  • node.js oracledb 不插入也不更新

    节点 oracledb 版本 1 2 节点 v0 12 7 按预期选择工作 对于更新和插入 虽然我们得到 rowsAffected 1 但插入或更新不受影响 var oracledb require oracledb oracledb ge
  • 使用本地存储存储多个项目的复选框“已选中”

    我想将我的复选框保存到本地存储 但是我使用的这段代码对于多个复选框来说太麻烦了 有没有更好的方法来做到这一点 setStatus document getElementById LineOp setStatus onclick functi
  • 调用其他程序时Powershell变量扩展

    我在尝试使用解压缩文件时遇到一个小问题7za http 7 zip org download htmlPowershell 中的命令行实用程序 我设置了 zip source变量为 zip 文件的路径和 unzip destination到
  • 在 Vue.js 中使用异步/等待模式

    我想在我的新 Vue js 项目中使用 async await 模式 然而 在我第一次尝试后 它抛出了一个错误
  • TreeMap 是如何排序的

    如何TreeMap种类 举例来说 您有以下地图 TreeMap
  • 当互联网断开连接时,HttpClient PostAsync 不响应

    我有一个 xamarin 表单应用程序 该应用程序执行PostAsync调用将图像作为多部分内容上传 问题是在 iOS 设备中 当我在 PostAsync 调用期间关闭 wifi 移动数据时 HttpClient 不会进入 catch 块来
  • 如何从C#读取中文文本文件?

    如何使用 C 读取中文文本文件 我当前的代码无法显示正确的字符 try using StreamReader sr new StreamReader path System Text Encoding UTF8 This is an arb
  • 如何将JScrollPane布局设置为与JTable相同?

    Tabel1 setModel new DefaultTableModel x y JScrollPane pane new JScrollPane Tabel1 当我运行该程序时 滚动窗格看起来比表格大 如何使滚动窗格布局与表格相同 ho
  • Angular 4 - 获取输入值

    我想知道如何从角度 4 上的输入获取值 我查看了有关 Angular 的文档 并且带有关键事件的示例对我来说效果不太好 我找不到正确的示例如何做到这一点 所以请帮助我 问题 我尝试读取输入的值 然后将值提交到另一个组件 该组件会将值添加到选
  • 如何在opencv中使某些像素透明?

    我用 for 语句检查了每个像素的亮度 并尝试在亮度超过 100 时使其透明 但隐形是行不通的 看代码 image al x y 的第四个是alpha 我应该怎么办 如果你使用 bgr 的值而不是透明度 它就会改变 image cv2 im
  • symfony2 - Doctrine - 如何使用计数和分组进行多重选择

    在 Symfony2 和 Doctrine 中 我想执行一个返回计数和分组依据的查询 这是我尝试过的 这是我要运行的 SQL SELECT terrain id COUNT FROM Partie WHERE 1 1 GROUP BY te
  • 扩展/插件通信的架构

    一旦解决了加载插件的问题 在 NET 中 在例外情况下通过 MEF 下一步要解决的是与它们的通信 简单的方法是实现一个接口并使用插件实现 但有时插件只需要扩展应用程序的工作方式 并且可能有很多扩展点 我的问题是关于如何处理这些扩展点 我已经