Translating ModuleInfo[] to IMyModule[]

Topics: Prism v2 - WPF 3.5
Jan 22, 2010 at 8:36 AM

Hi, I'm trying to inject an array of IProductModule (from which all of the modules in my application derive) without much success!  I've got a ViewModel for my Shell Window which I'm trying to inject an array of IProductModule (which derives from IModule) in order to be able to bind to the screen as "Module Buttons" with their own events which are inherited from IProductModule.  Below, I've pasted the code for my Bootstrapper (in order of execution) to give you an idea of what I'm doing (and perhaps not doing):

    public class Bootstrapper : UnityBootstrapper
    {
        protected override void ConfigureContainer()
        {
            Container.RegisterType<IProductModule[]>();

            base.ConfigureContainer();
        }

        protected override IModuleCatalog GetModuleCatalog()
        {
            return new ModuleCatalog()
                .AddModule(typeof(ProductAModule));
        }

        protected override DependencyObject CreateShell()
        {
            var view = Container.Resolve<ShellView>();
            var viewModel = Container.Resolve<ShellViewModel>();

            view.DataContext = viewModel;
            view.Show();

            return view;
        }
    }

The following code shows my ShellViewModel's constructor.  It's here that I'm attempting to inject the array of IProductModules, however, they never get injected.  (I'm not suprised as I'm never actually doing anything special to populate them other than my populating the ModuleCatalog).  Is there something that can be done to map my IProductModules into an array which can be injected into my ShellViewModel without having to create or initialize the modules twice?

    public class ShellViewModel : ViewModelBase
    {
        public IProductModule[] Modules { get; set; }

        public ShellViewModel(IProductModule[] modules)
        {
            Modules = modules;
        }
    }

Many thanks for reading and sorry for potentially asking something thats very easy to solve!!

Rob

Jan 22, 2010 at 7:55 PM

Hi Rob,

In the code above you are using the following line to register the IProductModule array:

Container.RegisterType<IProductModule[]>();
However, the line above is not mapped to any particular implementation, as the RegisterType method is used to provide a type mapping usually between an interface an one of its implementations. You can check the RegisterTypeIfMissing in the UnityBootstrapper to see how it works.

What you need to do is create an instance of IProductModule[] (and fill it with the instances that implement IProductModule), and register that instance in the container. A very simple example is shown below:

IProductModule[] modules = new IProductModule[] { productModuleInstance1, productModuleInstance2, …};
container.RegisterInstance<IProductModule[]>(modules);
Take into account that each of the IProductModule instances (which I assume) implements IModule belong to different modules, placing them in a single array might be breaking your modules decoupling.

To check how to “translate” from ModuleInfo to IModule instances you can check the ModuleInitializer class in the Microsoft.Practices.Composite assembly. If you want to access the ModuleInfo of all your modules, you can get the IModuleCatalog instance of your application injected and use its Modules property (IEnumerable<ModuleInfo>).

Please let me know if this helps.

Damian Schenkelman
http://blogs.southworks.net/dschenkelman

Jan 25, 2010 at 8:47 AM
Edited Jan 28, 2010 at 2:40 PM

Hey Damian,

I've posted my solution as "answered" on Stack Overflow but someone's informed me that the solution (which I'm using and happy with) is creating each module twice, once for my IProductModule collection and once for the IModuleCatalog.  Is there a method you could suggest which would not require the double-creation of my IProductModules but would still allow me to use buttons as a menu for the modules?

Many thanks (and apologies to bother you again!)

 

Rob