Anton Shakalo
Anton Shakalo

Reputation: 458

Prism unity container per module

I have two modules in my app, and want to register types for a second module in a separate container. Didn't find any ways to do that.

Only way I see now is add prefixes to reusable types like that:

    var foo1 = new Foo("FOO 1");
    parentContainer.RegisterInstance<IFoo>("Foo1", foo1);

    var foo2 = new Foo("FOO 2");
    parentContainer.RegisterInstance<IFoo>("Foo2", foo2);

    parentContainer.RegisterType<IService1, Service1>(new ContainerControlledLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IFoo>("Foo1")));
    parentContainer.RegisterType<IService2, Service2>(new ContainerControlledLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IFoo>("Foo2")));

Is there any way to configure prism to use another container for module?

Upvotes: 1

Views: 1303

Answers (1)

Sumit Datta
Sumit Datta

Reputation: 120

There is no direct way of passing a new container(child/no child) while every module initialization. I had a similar situation, where I needed modules to register their types in a specific unity container (child). This is how I did it.
First of all, I created a new Unity container inherited from UnityContainer. Created a dictionary of child containers as per the module names in the catalogue.

public class NewContainer : UnityContainer
{
    private readonly IDictionary<string, IUnityContainer> _moduleContainers;

    public NewContainer(ModuleCatalog moduleCatalog)
    {
        _moduleContainers = new Dictionary<string, IUnityContainer>();
        moduleCatalog.Modules.ForEach(info => _moduleContainers.Add(info.ModuleName, CreateChildContainer()));
    }

    public IUnityContainer GetModuleContainer(string moduleName)
    {
        return _moduleContainers.ContainsKey(moduleName) ? _moduleContainers[moduleName] : null;
    }

}

Now every module which I implement must be implemented from ModuleBase which uses child containers provided for that module in the parent UnityContainer. Register your types in the child container now.

public abstract class ModuleBase : IModule
{
    protected IUnityContainer Container;

    protected ModuleBase(IUnityContainer moduleContainer)
    {
        var container = moduleContainer as NewContainer;
        if (container != null)
            Container = container.GetModuleContainer(GetType().Name);
    }

    public abstract void Initialize();
}

This is how I used the container in my bootstrapper -

public class NewBootStrapper : UnityBootstrapper
{
    private readonly ModuleCatalog _moduleCatalog;
    private DependencyObject _uiShell;

    public NewBootStrapper()
    {
        _moduleCatalog = Prism.Modularity.ModuleCatalog.CreateFromXaml(new Uri("/projectName;component/ModulesCatalog.xaml",
                UriKind.Relative));         
    }

    protected override IUnityContainer CreateContainer()
    {
        return new DocumentBootStrapperContainer(_moduleCatalog);
    }
    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new AggregateModuleCatalog();
    }
    protected override void ConfigureModuleCatalog()
    {
        ((AggregateModuleCatalog)ModuleCatalog).AddCatalog(_moduleCatalog);
    }
}

Upvotes: 1

Related Questions