0

我正在开发一个与科学仪器交互的 .Net 桌面应用程序。这个工具有许多变体,每个都有不同的特性、组件等,所以我提出了一个插件/模块化架构,其中“模块组件”包含所有必要的业务逻辑、UI 等与该硬件组件/功能交互。

目前我有一个包含所有内容的解决方案——“核心”应用程序项目、公共库以及“模块”项目。我们的想法是我们将全部安装到客户站点(而不是挑选他们需要的 DLL),并使用包含所需模块列表的配置文件“激活”相关模块。

主应用程序项目使用 Castle Windsor、AssemblyFilter 和自定义 InstallerFactory 加载模块。它搜索每个模块程序集,寻找一个实现IWindsorInstaller 装饰有特定自定义属性(具有包含模块名称的属性)的类。仅当属性的模块名称是请求的名称之一时,才会运行模块的安装程序。这些安装程序类负责向 Windsor 注册该模块所需的一切(业务逻辑、视图、视图模型等)。

这个解决方案在我的概念证明中运行良好,但是我可以看到两个或多个模块在功能上非常相似的场景,因此需要共享公共代码。假设我有项目“ModuleA”和“ModuleB”,他们的 Windsor 安装程序IFooService在项目“ClassLibraryX”中注册了相同的类。该应用程序将失败,因为 IFooService 已被重新注册两次,并且当构造函数请求时,Windsor 将不知道要解决哪个问题。

处理这个问题的最佳方法是什么?思念至今:-

  • 查看特定组件是否已在 Windsor 中注册。这感觉很hacky(如果可能的话)
  • 使用名称注册组件,但是如何通过构造函数注入请求命名实例?
  • 在每个模块项目中创建一个新接口,例如public interface IModuleAFooService : IFooService,并在整个项目中注册/使用它(而不是IFooService)。

有什么想法吗?

编辑:事实上,温莎在尝试解决时不会摔倒IFooService。当第二个模块尝试注册相同的接口/具体实现时,它将崩溃!

4

3 回答 3

0

在我看来,你有几个选择。我认为你有两个主要问题。首先是您要安装共享接口两次(或更多次)。第二个是您可以拥有两个不同版本的共享接口。

对于第一个问题,我会将共享接口分离到它们自己的程序集中。在该程序集中,我将有一个适用于该程序集的安装程序。然后,您可以告诉 Windsor 安装该共享组件,它知道如何连接自己。

对于第二个问题,您有两个选择(如我所见)。第一种选择是保持共享组件向后兼容。第二种选择是隔离您的运行时(通过应用程序域或进程)。

于 2012-09-21T11:41:49.517 回答
0

命名实例没问题。DependsOn(Dependency.OnComponent("paramName", "serviceName"))您可以通过fluent 配置中的方法定义对具体命名服务的依赖。

于 2012-09-24T07:20:27.590 回答
0

你不能为插件提供一些元数据,即给每个插件实现一个名称属性,windsor 可以使用它来识别你想要的实现吗?

我最近没有过多使用 Castle,但我确信它确实有命名绑定/注册的概念,所以你可以用它作为区分事物的一种方式,如果这不可能并且没有其他元数据您可以考虑使用 which 会使 Windsor 变得不那么模棱两可,然后我会选择您的第三个选项。

刚刚再次阅读了您的第二个选项(在编写上述内容之后),这似乎是最好的选择,我不记得确切的语法,但在大多数 DI 框架中,您会执行以下操作:

var instance = Get<IMyInterface>("Named This");

他们的文档中的某处将有大量语法示例,但您需要知道 Windsor 端的名称才能注册它,并在客户端请求它。

于 2012-09-21T10:51:40.190 回答