问题标签 [compositionroot]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - caliburn.micro、Bootstrapper 和 CompositionRoot
我试图了解 CompositionRoot 的含义。
到目前为止,我从未找到关于它是什么的深入描述,只是对不应该做什么的简短陈述。
使用 caliburn.micro 时出现的 Bootstrapper 是否已经意味着“CompositionRoot”?
或者它更接近于 servicelocator 反模式,因为它只能提供程序集内部的任何内容及其依赖项。
如果有人对 CompositionRoot 有很好的描述,请分享。我已经知道 ploeh 博客了。
如果我看到 CompositionRoot 带来更好的架构和/或帮助我解决问题,我仍然愿意购买这本书。但是我知道周围没有足够的信息让我看看它会有什么帮助。
更新
假设我所有的 ViewModel 都注入了 EventAggregator(构造函数注入)。现在我想在需要时动态创建这些 ViewModel。我可以预先注册类型(在 CompositionRoot 中),但以后如何解决依赖关系?据我了解,在组合根之后不应该触及容器。毫无疑问,我不想在需要它们之前创建所有实例(这会使应用程序启动缓慢)。“注册-解决-发布”是这里的意思吗?(这种模式也是在 ploeh 博客中创造的)
dependency-injection - 具有隔离的分层应用程序中的 DI
假设我们有三层;用户界面、业务、数据。我们正在使用 DI。我不希望从 UI 访问数据层。

问题是关于数据层的DI注册。组合根在 UI 中,我不想在那里对 Data 有任何引用。我找到了这个答案。据我了解,我们应该参考所有层,并认为它们是库而不是层。这样我可以指定我的业务层使用数据层或我想要的任何其他东西。毕竟这就是 DI 存在的原因。
没错,但是有问题!我们不应该在 UI 中使用数据层。但是一旦一个开发者不小心从 UI 引用到了 Data,而另一个开发者直接从 Data 层注入了一些东西到一个 UI 类中。所以他跳过了我从不想要的业务层。
我该如何处理这种情况?我想有一些限制,但另一方面我想要 DI 的灵活性。
当然,有些人认为我们可以有一个单独的库,只用于依赖注册。

这里最好的模式是什么?
c# - 组合根需要单元测试吗?
我试图找到答案,但似乎并没有直接讨论很多。我有一个应用程序的组合根,在其中创建一个 DI 容器并在那里注册所有内容,然后解析获得所有依赖项所需的顶级类。由于这一切都发生在内部 - 很难对组合根进行单元测试。你可以做虚拟方法、受保护的字段等等,但我不喜欢引入这些东西只是为了能够进行单元测试。其他类没有大问题,因为它们都使用构造函数注入。所以问题是 - 测试组合根是否有意义?它确实有一些额外的逻辑,但不多,在大多数情况下,应用程序启动期间会弹出任何故障。我有一些代码:
.net - 我应该在“主要”方法中编码什么?
也许这是一个太宽泛的问题,但我仍然想听听什么是最佳实践以及什么被认为是“正确的”。我没有找到类似的主题,可能是因为它是通用的,因此很难搜索。
这一切都始于我们采用了一个 Windows 服务项目并向其中添加了另一个服务。以前,main 方法是我们认为的Composition Root,而我们的 IoC 容器注册代码、app.config 读取等类似的形式以一种或另一种形式存在于 main 方法中。在组装所需的依赖项之后,我们通过调用Resolve容器并运行它来创建服务。
当我们创建另一个继承自的类时,ServiceBase我们注意到将 main 作为组合根不再有意义,因为多个服务可能完全不同,因此需要不同的初始化代码。
我在数学上发现的唯一有启发性的帖子是来自 Mark Seemann 的这篇文章,他在其中指出,这OnStart将是聚合根(在这种特殊情况下)。
一般来说,在选择和适当的组合根时采取的最佳方法是什么?我是否应该将此 Windows 服务场景视为异常值,并为其编写不同的代码,同时将 main 方法保留为其他项目类型的组合根,或者是否有更通用的方法在所有情况下都有效?
也许服务需要非常不同的设置这一事实表明它们应该在多个独立项目中分开,其中 main 将再次用作组合根?
我们通常使用 .Net,但这可能也适用于许多其他编程语言。
unit-testing - 如何测试我的工厂是否正确绑定?
使用Ninject,我有以下内容并希望使用FluentAssertions进行测试:
有什么好的方法可以测试工厂是否真的绑定正确?
php - 你可以有多个组合根吗?
我有一个 PHP 命令行实用程序,执行如下:
这个想法是可以使用 3rd 方插件,因此主要工具不知道它们是什么。它可以通过环境变量找到它们,就像PATH.
主工具应用程序有一个组合根,其中包含所有插件(共享)使用的依赖项。但是,每个插件都有自己的依赖项,因此,插件的构造函数是我拥有第二个组合根的地方。
这听起来像是多个组合根的合理案例吗?
第二个问题
每个命令都有一个 Option 对象数组,我不确定 Command 是否应该预先组合和注入这个数组,或者是否应该将 OptionFactory 注入到命令的构造函数中。后者很好,因为它将选项封装在命令中,而插件的构造函数必须为它支持的每个命令构建一个选项列表。请注意,这些不是命令行选项 ( $argv),它只是命令支持的选项列表并包括一个验证器。
c# - 是否有 Windsor 扩展点或通用 IoC 技术来处理在一个根下的许多场景中所需的原始依赖项?
背景
我有许多由依赖于要创建的连接字符串的组件实现的服务 - 例如:
我通常更喜欢第一个构造函数而不是第二个构造函数,因为为了使用连接字符串,我必须创建一个与它的连接,这反过来又需要解析IOracleConnection依赖string项。
MyIImportantController有一个构造函数和参数IImportantRepository。MyIControllerFactory是组合根(不包括引导程序),并IWindsorContainer.Resolve<T>()在运行时用于激活作业的正确控制器。
所以我想整个事情在引导时看起来像这样:
这在请求时:
动机
现在,在一个应用程序中,IOracleConnection(以及构建它的底层字符串)在以下情况下可能是已知的:
- 应用程序被设计(用于测试的虚构连接字符串)
- 应用程序已编译(完全由构建变量确定的连接字符串)
- 应用程序已部署(转换中设置的连接字符串
web.config) - 应用程序被引导(在配置源中设置的连接字符串只读一次)
- 应用程序处理某种类型的请求(例如,“通常”但不是“总是”您想要显示来自的数据
ProductionDb) - 应用程序处理一个连接被参数化的请求(一个管理
Important东西的请求,ChicagoDb而不是NewYorkDb,或其他) - 应用程序处理一个请求,其中会话或用户详细信息完全决定了连接(10% 的用户继续使用
Db1,其余用户Db2根据设计继续使用)
问题
您将如何编写可维护的代码而不过多地违反 DRY,从而同时为同一个图实现相同依赖项的所有这些潜在用途?
winforms - 将依赖注入类与容器传递到应用程序启动 WinForm
我正在开发一个 WinForms 应用程序,该应用程序已配置为典型的 3 层 UI、BLL 和 DAL。我创建了一个单独的项目作为启动项目。还创建了另一个项目作为自制的依赖注入容器,目的是执行所有依赖注入设置。自制的依赖注入容器由启动项目实例化,然后将实例化对象传递给第一个 WinForm。
自制的依赖注入容器实现如下所示:
启动项目如下图所示:
接收 WinForm 使用注入的对象进行如下实例化:
WinForm 在以下两个按钮单击事件中使用注入的对象:
这目前没有太大问题,因为我只传递了 2 个注入的对象。但是,如果对象的数量增长到超过 5 个,这似乎是一个问题,那么我将向启动 WinForm 传递超过 5 个参数。如果我决定将名为 AppDependencyInjection 的自制依赖注入容器而不是单独的注入类传递给 WinForm,我可以将要传递的参数限制为一个。如果我这样做,它将使表示层依赖于自制的依赖注入项目,从而使表示层同时依赖于 BLL 和依赖注入项目。这可以接受吗?我还能做些什么来适应应用程序中依赖注入类的未来增长?
c# - 组合根与服务定位器
我一直在阅读这两种解决依赖关系的方法,并找到了一些用于 ninject 实现的示例代码。
对于服务定位器遵循类似
和
开箱即用的课程
对于组合根我遵循 - https://gist.github.com/paigecook/3860942
并对 NinjectWebCommon进行了一次更改Create(..)。
编辑
控制器和服务创建
我是否正确实现了合成根?我真的不明白这两种方法有什么区别?