Why is the MEF container not available in modules?

In my Prism application, the MEF container is accessible from the Bootstrapper class via the Container property.

But this is not from within the class module (IModule). I can import the container only through IServiceLocator.

Why? I thought it made sense to use a common interface for specific technologies, but the Prism 4.1 manual asks us not to use IServiceLocator (in Considerations for using IServiceLocator ).

+6
source share
2 answers

I think that this does not correspond to Prism or MEF, but to the principle of dependency injection and the best methods in general. (Yes, I am tying that MEF is not a DI container, but here it is used almost like a DI container, so I suggest using the same methods here).

In DI best practices ( this book is very cool, I highly recommend it), it’s good to have these steps in the DI "workflow":

  • register all necessary types (in Prism mode - by Bootstrapper.ConfigureCatalog ())
  • allow the root object (with all nested objects). In Prism, by the Bootstrapper.CreateShell () method)
  • use your root object
  • free root object

Ideally, you should NOT use the DI container anymore. Your code should not know about the existence of a DI container (on this side, Unity really is a DI container, because you can write code that does not know about using a DI container). If your code knows about this, it DEPENDS on the DI container, and this is bad.

PS. If you still want to use the MEF container in your module (for example, because you are not very familiar with the DI paradigm or you have some specific tasks), you can try something like:

[ModuleExport(typeof(YourModule))] public class YourModule : IModule { public static CompositionContainer CompositionContainer; [ImportingConstructor] public void YourModule(CompositionContainer container) { this.CompositionContainer = container; } } 

Remember to register your MEF container in your Boostrapper:

 public class YourBootstrapper: MefBootstrapper { protected override CompositionContainer CreateContainer() { var container = base.CreateContainer(); container.ComposeExportedValue(container); return container; } } 
+6
source

Please note that I am using an older version of Prism and that I am using it with UnityContainer, but the same principles should apply.

Define your module class to take the container in the constructor.

Here is an example of using Unity:

 public class Module : IModule { public static IUnityContainer Container; public Module(IUnityContainer container) { Container = container; } } 

If you define a constructor that accepts a container, it will be called by the ApplicationBootstrapper.Run () method.

I tested with a constructor with no default parameters and an overload constructor that takes the container, and the second constructor was called.

I also checked for only the default constructor, and it got a call. I would suggest you change your constructor to add a parameter that accepts a container.

Having a container in your module class will allow you to register types in the Initialize method.

As for ServiceLocator, this is a slightly different template that I would recommend you to use in cases where for some reason you cannot get your dependencies created by the container.

0
source

Source: https://habr.com/ru/post/916995/


All Articles