我正试图在我的应用程序中实现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")
现在我对此有一些疑问:
>我对工厂调用新组件(…)感到高兴.难道这不是穷人的DI吗?
>使用Func< IService>时,好莱坞原则是否仍然有效?在工厂的构造函数?我的意思是,它最终调用container.Resolve<> …有点像SL.唯一的区别是代码位于应用程序的容器注册部分而不是工厂类.
>就DI和IoC而言,这个实现有什么问题吗?
最佳答案 >距离穷人的DI还有很长的一步,但如果你不必每次在Component的构造函数中添加新的依赖项时都不需要更改这个工厂方法,那就太好了.
>这本身不是问题.想想它就像你正在注入一个匿名的工厂类.它仍然可以用于单元测试,并且绑定可以更改,因此您仍然可以获得DI的好处.但它是一个额外的抽象层,可能没有必要.在这种情况下,您仍然可以通过将IService直接注入工厂而不是Func来避免它.
>通常在使用依赖项注入时,您希望注入服务而不是值.您发现必须同时拥有这两者的事实可能表明您需要重新考虑您的类的API.例如,也许您应该将值传递给类上的方法而不是构造函数.如果不了解更多细节,很难说最好的方法是什么.