我正在尝试在我的应用中实施IoC。我有这个模型:
interface IService;
interface IComponent;
class Service : IService
Service()
class Component : IComponent
Component(IService service, object runtimeValue) { }
在我的应用中,我需要获得IComponent
。我的应用程序使用IoC容器(Unity)。我可以在容器中注册Service
,但我不能对其Component
的{{1}} b / c进行同样的操作。根据{{3}},我必须使用工厂并在我需要的任何地方注入runtimeValue
:
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<>
...并将容器注册为静态工厂,以便它回调容器来解析服务(我在.net 2.0上使用Unity 1.2):
class ComponentFactory : IComponentFactory
ComponentFactory(Func<IService> serviceFactoryDelegate)
IComponent CreateComponent(object runtimeValue) {
return new Component(serviceFactoryDelegate.Invoke(), runtimeValue)
}
现在我可以使用容器来解析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不是吗?
在工厂的构造函数上使用new Component(...)
时,好莱坞原则是否仍然有效?我的意思是,它最终调用container.Resolve&lt;&gt; ...有点像SL。唯一的区别是代码在应用程序的容器注册部分而不是在工厂类中。
就DI和IoC而言,这个实现有什么问题吗?
答案 0 :(得分:1)
IService
的实例它比它需要的要复杂一些。为什么双重定向IComponentProvider
- &gt; IComponentFactory
?看起来IComponentFactory
没有任何好处。
像这样实施ComponentProvider
:
class ComponentProvider : IComponentProvider
{
ComponentProvider(IService service) { _service = service; }
IComponent CreateAndCacheComponent(object runtimeValue) {
_component = new Component(_service, runtimeValue);
return _component;
}
这会给你以下好处:
IComponentFactory
以及相应的实现。IService
一般来说,你如何实现它取决于你真正需要的东西:
“runtimeValue”在整个运行时可以是相同的,例如从设置中读取的连接字符串。在这种情况下,不需要工厂/提供者,您可以简单地新建实例并将其注册到容器中。需要IComponent
的每个人在构造函数中请求一个而不是提供者。
如果“runtimeValue”在调用CreateAndCacheComponent
之间真正发生变化,那么你只会实现一个工厂并将其作为依赖关系传递。
答案 1 :(得分:1)
IService
直接注入工厂而不是Func
来避免它。答案 2 :(得分:0)
问题1:在工厂中调用new
没有错。您已将实例化隔离到应用程序中的一个位置;你只是把它放在工厂而不是容器里。
如果您需要模拟或更改实现,您只需模拟或更改工厂实现,而不仅仅是组件。