ServiceLocator RegisterTypeIfNotYetRegistered

Topics: Feature requests
Aug 31, 2012 at 6:25 PM

Hi Geert,

after using the latest nuget beta libraries, it seems to me that the RegisterTypeIfNotYetRegistered function does not work anymore as expected....

// register custom UIVisualizer here first
// to prevent catel from registering it's own UIVisualizer
// in ViewModelServiceHelper.RegisterDefaultViewModelServices
serviceLocator.RegisterTypeIfNotYetRegistered<IUIVisualizerService, Services.UIVisualizerService>();
// register other ViewModel services
ViewModelServiceHelper.RegisterDefaultViewModelServices(serviceLocator); // at this point catel UIVisualizer is registered... not my custom UIVisualizer (was overwritten)...

Could you please take a look at this? Many Thanks!

Aug 31, 2012 at 9:38 PM

Now you are not able to prevent the service registration unless you load Catel.MVVM assembly after you register you own service.

All Catel.MVVM services are registered during the module initialization via ModuleInit.Fody.

So, now you must override the existing services instead prevent registration.

Aug 31, 2012 at 9:42 PM

Indeed. We introduced a new ModuleInitializer. This means that as soon as a library is loaded by the .NET framework, we can execute code. This solves issues around the chicken-egg problem where you need to register the IUIVisualzier service before you can use it, but it is only registered at the first time you hit a ViewModelBase.

This problem is now solved, but you must overwrite the instance (thus use RegisterType instead of RegisterTypeIfNotYetRegistered.

Sep 4, 2012 at 12:10 AM
Edited Sep 4, 2012 at 12:10 AM

Thanks for your reply. It took me some time to dig through but i think the Catel ServiceLocator (latest sources) has a problem with synchronizing an external container (unity) if re-registering a type. The Catel Service Locator is updated correctly but not the external container if AutomaticallyKeepContainerSynchronized.....

An example to demonstrate what i did:

           Catel.IoC.ServiceLocator.Instance.AutomaticallyKeepContainersSynchronized = true;

            // register my custom services through catel
            Catel.IoC.ServiceLocator.Instance.RegisterType<IUIVisualizerService, Services.UIVisualizerService>();

            // register my custom service through unity directly
            Unity.Instance.Container.RegisterType<IUIVisualizerService, Services.UIVisualizerService>();

            // get service through catel
            var x = Catel.IoC.ServiceLocator.Instance.ResolveType<IUIVisualizerService>();

            // get service through unity
            var x1 = ServiceLocator.Instance.GetInstance<IUIVisualizerService>();

            // both containers are equal now with the same service
            // x == x1

            // register standard catel service (should be also exported to external container)
            Catel.IoC.ServiceLocator.Instance.RegisterType<IUIVisualizerService, UIVisualizerService>();

            // get service through catel
            x = Catel.IoC.ServiceLocator.Instance.ResolveType<IUIVisualizerService>();

            // get service through unity
            x1 = ServiceLocator.Instance.GetInstance<IUIVisualizerService>();

            // the containers are not equal anymore with the same service
            // unity container points to custom service
            // catel container points to standard service
            // x != x1


Could you please take a look at this issue? Thanks a lot!

Sep 4, 2012 at 8:50 AM

I rewrote your code into a unit test. When re-registering the type, the ServiceLocator checks whether the type is already registered in the external container. This is the case and Catel will not overwrite the registration.

I can always overwrite the registration, but this can be very, very tricky. Therefore I recommend that you make sure the Catel ServiceLocator is correctly filled. Then, after that, call the RegisterExternalContainer and all will work out of the box.

Sep 4, 2012 at 10:43 PM

Thanks a lot for the hint. I was able to fix my initialization problem.