IOC Container, Go Hide (part 2)
Ok, there seem to be some misunderstanding with the suggestion from my previous post.
A framework manipulates two kind of objects :
- its objects
- your objects
You don’t care about its object, you care about yours.
So you want to be able to take part in your objects instantiation so that you can do your own stuff (inject dependencies, handle differently based on runtime behavior…).
Without container
Look at Asp.net, when it needs to create an Http Handler, it calls a IHttpHandlerFactory.
You can provide your own IHttpHandlerFactory, just implement its two methods (the second one can even be left empty in most cases) :
public interface IHttpHandlerFactory { // Methods IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated); void ReleaseHandler(IHttpHandler handler); }
In the GetHandler method, you’re free to use the container you want ! But you can also do this :
return new CustomHttpHandler(theDependency);
Or make a call to another factory, or… or…
With container
The framework ask to provide a container so that the it can simply run. Ok there is also a builtin container so I don’t have to care.
But if I want to do a custom instantiation I have now to implement the following interface :
public interface IServiceLocator : IServiceProvider { // Methods IEnumerable<TService> GetAllInstances<TService>(); IEnumerable<object> GetAllInstances(Type serviceType); TService GetInstance<TService>(); TService GetInstance<TService>(string key); object GetInstance(Type serviceType); object GetInstance(Type serviceType, string key); }
This interface will be used when any instantiation will occur. If I mess internal framework instantiation. Wooch !
And there is no clear meaning with this interface. It should be able to instantiate any object requested.
It doesn’t give a clean and clear API in my personal opinion !
Using an IOC container as an extension point is clearly an over abstraction !
Provide clear, focused extensibility points
The framework doesn’t need to be extended on every instantiation, especially when instantiation its own internal stuff. There are clear extension points, and a specific interface should be created for each.
This is just a framework design good practice.
Then, there is no need to show the container you use to the outside, and it resolves potential version conflicts.