使用依赖注入时使用工厂创建多个对象
我试图弄清楚如何在使用依赖注入时创建多个对象。据我了解,标准方法是注入一个工厂,然后用于创建对象。我纠结的部分是工厂如何创建对象。到目前为止,我看到了两种可能的解决方案:
工厂只是使用 new() 来创建对象。
- DI 不应该让我不再对非值对象使用 new 吗?
- 如果要创建的对象具有可由 IoC 解决的依赖关系,会发生什么情况?
使用容器作为 Serviclocator
- 解决了仅以引入反模式为代价新建对象的问题,或者如果serviclocater的使用仅限于工厂内,它就不再是反模式了?
感觉我可以在一个糟糕的解决方案和一个糟糕的解决方案之间做出选择。我是否遗漏了什么或者我理解有问题吗?
编辑 目前我根本不使用 Ioc,而是考虑 Ninject。尽管 Autofac DelegateFactories 听起来很有前途。
I am trying to figure out how to create multiple objects when using Dependency Injection. As far as I understand the standard approach is to inject a Factory which is then used to create the objects. The part I struggle with is how the Factory creates the objects. So far I see two possible solutions:
The Factory just uses new() to create the object.
- Isn't DI supposed to free me of the use of new for non value objects?
- What happens if the Object to be created has dependencies that could be resolved by the IoC?
Use the Container as Serviclocator
- solves the problems of just newing objects at the cost of introducing an antipattern or is it no longer an antipattern if the use of the serviclocater is constraind within the factories?
It feels like i can coose between a bad and a bad solution. Is there something I am missing or do I understand somthing wrong here?
Edit Currently I am not using an Ioc at all but thinking about Ninject. Although the Autofac DelegateFactories sound very promising.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,我不认为在工厂中使用容器作为服务定位器是一种反模式。在某些真实情况下,这是完全合适的。想想看,容器感知工厂实际上是容器扩展,而那些似乎被排除在服务定位器攻击之外。即使是最纯粹的 IoC 框架(例如 AutoFac 或 Ninject)也具有广泛的扩展功能。此模式最典型的用例是根据服务的使用位置解析不同的实现。
关于使用 new 在工厂内创建实例,这也是可以接受的。 IoC/DI 消息在那里有点扭曲,并且从不使用
new
实际上是一个副作用,而不是 DI 的目标。依赖注入的首要任务是从组件中外部化依赖项的创建。只要工厂本身被注入到组件中,它就满足了这一要求。在评估此类场景时,您需要问自己的问题是:我之前说过,IoC 容器只是类固醇工厂。对于 80% 的用例,它们开箱即用。另外 20% 可能需要对上述两个品种进行调整。当我想要创建需要注册依赖项和运行时一些输入的组件时,我倾向于使用容器感知工厂;当我创建不依赖于其他对象的域对象时,我倾向于使用新工厂。服务,但在运行时获取它们的所有构造参数。
For starters, I don't consider using a container as service locator in factories an anti-pattern. There are genuine circumstances where it is entirely appropriate. Come to think about it, container aware factories are really container extensions, and those seem to be excluded from service locator bashing. Even the most pure IoC frameworks like AutoFac or Ninject have extensive extension capabilities. A most typical use case for this pattern is resolving to different implementations based on where the service is used.
With regards to using
new
to create instances inside factories, that is acceptable as well. The IoC/DI message got a bit distorted there and never usingnew
is really a side effect, rather than the goal of DI. The first imperative of Dependency Injection is to externalise creation of dependencies from the component. A factory satisfies that imperative as long as it itself gets injected into component. The questions you need to ask yourself when evaluating such scenarios are:I said this before, IoC containers are just factories on steroids. For 80% use case they work out of the box. The other 20% might require tweaks of the above two varieties. I tend to use container aware factories when I want to create components that require both registered dependencies and some input at run-time and
new
-ing factories when I create Domain objects that don't have dependencies on other services, but take all their construction parameters at run time.尽管工厂的接口将在应用程序级别定义,但您通常会定义接近 DI 配置的工厂类的实现,因此作为 组合根。尽管直接从代码调用容器是服务定位器反模式<的实现/a>,在组合根中定义的任何代码都只是 机制,因此不是服务定位器。只要新建对象或调用容器是在组合根内部(或非常接近)完成的,这不是问题,因为应用程序仍然不会受到任何定位器/容器的影响。
换句话说:使用工厂方法。您是否需要直接在工厂内
新建
对象或使用容器,取决于对象。让容器创建对象是更好的选择,特别是当它们有自己的依赖项时,但并非所有对象都可以由容器创建。在这种情况下,您需要恢复到new
操作。当代码是组合根的一部分而不是应用程序的一部分时,两者都很好。工厂本身可以有自己的依赖项。这应该不是问题。您可以让容器连接工厂实例。Although the interface for your factory will be defined at the application level, you would typically define the implementation of that factory class close to your DI configuration, thus as part of your composition root. Although calling the container directly from your code is an implementation of the Service Locator anti-pattern, any code that is defined inside the compostion root is merely mechanics and is therefore not Service Locator. As long as newing up objects or calling into the container is done inside (or very close to) the composition root, this is not a problem, because the application will still be clean from any locator / container.
In other words: use the factory approach. Whether or not you need to
new
up objects directly inside your factory or make use of the container, depends on the objects. Letting the container create the objects is preferable, especially when they got dependencies on their own, but not all objects can be created by the container. In that case you need to revert to thenew
operation. Both are fine when the code is part of the composition root and not of the application. The factory itself can have dependencies of its own. This should not be a problem. You can let the container wire-up the factory instance.