I'm trying to implement IoC in my app. I have this model:
interface IService;
interface IComponent;
class Service : IService
Service()
class Component : IComponent
Component(IService service, object runtimeValue) { }
At some point in my app I need to get a IComponent
. My app uses a IoC container (Unity). I can register Service
with the container but I can't do the same for Component
b/c of its dependency runtimeValue
. According to this I have to use a factory and inject that wherever I need to get a 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
I must be able to register the factory with the container, so it must have only static dependencies. At the same time it must be able to provide a service instance of type IService
required to create a component.
Here is the factory implementation. The only thing I could think of was to use a Func<>
delegate as dependency:
class ComponentFactory : IComponentFactory
ComponentFactory(Func<IService> serviceFactoryDelegate)
IComponent CreateComponent(object runtimeValue) {
return new Component(serviceFactoryDelegate.Invoke(), runtimeValue)
}
... and register the delegate with the container as static factory, so that it calls back the container to resolve the service (I'm using Unity 1.2 on .net 2.0):
Container
.Configure<IStaticFactoryConfiguration>()
.RegisterFactory<Func<IService>>(container => (Func<IService>)container.Resolve<IService>)
Now I can use the container to resolve a ComponentProvider
and get a component based on a runtime value:
// this happens inside CompositionRoot
provider = Container.Resovle<IComponentProvider>()
component = provider.CreateAndCacheComponent("the component")
Now I have some questions about this:
I'm not happy that the factory calls
new Component(...)
. Isn't this poor man's DI?Does the Hollywood principle still stand when using
Func<IService>
on factory's constructor? I mean, it ultimately calls container.Resolve<>... kind of like SL. The only difference is the code is in the container registration part of the app rather than inside the factory class.Is there anything (else) wrong with this implementation, as far as DI and IoC are concerned?
IService
directly? – Daniel HilgarthFunc<IService>
? Isn't the whole point to allow your container to resolve this? – JayIService
dependency, then the same service instance would have been used in both methods. Using the delegate allows the container to resolve the service each time it is needed, using its configured lifetime. – Suiden