While working on Catel, I have faced several very difficult issues. On of the issues was: what IoC container should we use for Catel? In the beginning, when everything was simple, we decided to use Unity. However, this causes several additional dependencies to Unity while some people don’t even want to use Unity. Another issue was: what if Catel was used in a solution that already used a Unity container?
So after taking a step back, going back to the drawing table, I think I came up with something quite genius. If you don’t think so, please let me know, I always love to learn! It works on WPF, Silverlight and event Windows Phone 7!
Writing a custom IoC container
Don’t be scared, please hear me out. What I did was wrote another IoC container with methods to Register types and instances, check whether a specific type is registered and a method to resolve types. This IoC container class called IServiceProvider holds a dictionary of instances so it always returns the same instance of the type when a service is requested.
So until now nothing special, just a class holding references to services and the ability to create new instances if they don’t exist yet.
Supporting external containers and even one step further
The hard part about the issue is that people want to be able to use the IoC solution they prefer, not the one I prefer. So, there must be some way to allow the service locator to synchronize with other containers, or at least be able to use them in case types or instances cannot be found in the current service locator. Therefore, a RegisterExternalContainer method was added to the service locator to allow a developer to register an external IoC container. This is the final flow chart for the retrieval of types:

- First the service locator tries to resolve the type on it’s own.
- If that fails, it tries all of the registered external containers in the order in which they were registered.
- If that fails, the MissingType event is invoked which gives the developer a last chance to provide the type at runtime.
If the type cannot be resolved after step 3, then an exception is thrown. If the type can be resolved, the instance is stored in the service locator and can be return easily the next time it is requested.
How does the support for external containers work?
The next challenge to compete was the reference to Unity. How to remove it and how can other external containers easily be supported. The following architecture came up:

The class diagram above shows that there is a IExternalContainerHelper interface that defines how a helper class for an external IoC container should behave. It contains the basic methods such as RegisterType, RegisterInstance, IsTypeRegistered and ResolveType. Then, for every supported external IoC container, a helper class must be written. Catel currently supports Unity. The helper classes are registered in the ServiceLocator class and are used when a type cannot be resolved by the ServiceLocator itself.
The UnityHelper uses reflection to invoke the methods on the unity IoC container so the reference to the Unity assemblies are no longer needed. In the future, it is very easy to implement supported for other IoC containers because it only has to implement the IExternalContainerHelper interface.
So I use Prism, how does this work?
So you are using Prism? In the past, you had to manually map the registered types from the Prism Unity container to the Catel IoC container. Now this is the only thing you have to do:
1: IServiceLocator serviceLocator = Catel.IoC.ServiceLocator.Instance;
2: serviceLocator.RegisterExternalContainer(myPrismUnityContainer);
You can now use the IServiceLocator of Catel anywhere in your code and it will automatically use the Prism Unity container when needed.
This feature is already checked in, but will be officially available in Catel 2.0 (which is planned for the end of August, 2011). Interested in the source code? Check it out!