【发布时间】:2011-12-07 06:10:30
【问题描述】:
我正在尝试在我的应用中实现 IoC。我有这个模型:
interface IService;
interface IComponent;
class Service : IService
Service()
class Component : IComponent
Component(IService service, object runtimeValue) { }
在我的应用程序中的某个时间点,我需要获得IComponent。我的应用程序使用 IoC 容器 (Unity)。我可以在容器中注册Service,但我不能为它的依赖关系runtimeValue 的Component b/c 做同样的事情。根据this,我必须使用工厂并在我需要的任何地方注入IComponent:
interface IComponentFactory
IComponent CreateComponent(object runtimeValue)
class ComponentProvider : IComponentProvider
ComponentProvider(IComponentFactory factory) { }
IComponent CreateAndCacheComponent(object runtimeValue) {
_component = factory.CreateComponent(runtimeValue)
return _component
}
// other methods
我必须能够向容器注册工厂,因此它必须只有静态依赖项。同时它必须能够提供创建组件所需的IService 类型的服务实例。
这是工厂实现。我唯一能想到的就是使用Func<> 委托作为依赖:
class ComponentFactory : IComponentFactory
ComponentFactory(Func<IService> serviceFactoryDelegate)
IComponent CreateComponent(object runtimeValue) {
return new Component(serviceFactoryDelegate.Invoke(), runtimeValue)
}
...并将代理注册到容器中作为静态工厂,以便它回调容器来解析服务(我在 .net 2.0 上使用 Unity 1.2):
Container
.Configure<IStaticFactoryConfiguration>()
.RegisterFactory<Func<IService>>(container => (Func<IService>)container.Resolve<IService>)
现在我可以使用容器来解析 ComponentProvider 并根据运行时值获取组件:
// this happens inside CompositionRoot
provider = Container.Resovle<IComponentProvider>()
component = provider.CreateAndCacheComponent("the component")
现在我对此有一些疑问:
工厂打电话给
new Component(...)我很不高兴。这不是穷人的DI吗?在工厂的构造函数上使用
Func<IService>时好莱坞原则是否仍然有效?我的意思是,它最终调用 container.Resolve... 有点像 SL。唯一的区别是代码在应用的容器注册部分,而不是在工厂类中。就 DI 和 IoC 而言,此实现是否有任何(其他)问题?
【问题讨论】:
-
为什么需要委托?为什么不能直接注入
IService? -
为什么需要
Func<IService>?让你的容器解决这个问题不是重点吗? -
@Daniel, @Jay:注入服务假定将使用相同的实例来创建组件。如果工厂有另一个方法必须创建具有
IService依赖项的不同对象,那么两个方法中将使用相同的服务实例。使用委托允许容器在每次需要时解析服务,使用其配置的生命周期。 -
您通常不应该关心您的服务的生命周期,或者您是否获得与另一个消费者相同的实例。您真的需要不同的服务实例吗?
-
最后我遇到了其他人使用这样的 Func:nblumhardt.com/2010/01/the-relationship-zoo: 如果 A 需要创建 B 的实例,那么它需要一个 Func (我假设它会回调容器)
标签: c# dependency-injection inversion-of-control unity-container ioc-container