views:

206

answers:

2

In this stackoverflow question I learned that Prism/Unity is not as decoupled as I thought, e.g. if I have this class which gets menuManager injected into its constructor, then I have to make sure that this class actually exists somewhere (I thought that you could just pull the .dll that contains the class and the container would deal with it, e.g. injecting a null in its place):

public class EmployeesPresenter
{
    public EmployeesPresenter(IMenuManager menuManager)
    {

    }
}

But I can deal with that: the application cannot run without a MenuModule (or else as was suggested I could have a NullMenuModule which does nothing but keeps the application from breaking).

However, the application I am building will have a MenuManager class in the MenuModule and every module will have to register everything it wants to have in the menu with the MenuManager. However, I want to be able to swap out MenuModules e.g. have a InfragisticsMenuModule and have a TelerikMenuModule, etc.

However, when I am in e.g. the CustomersModule, in order to use TelerikMenuModule, I need to reference it. And when I want to use InfragisticsMenuModule, I need to reference that.

So how will I be able to "hot swap" TelerikMenuModule with InfragisticsMenuModule without recompiling all my modules with new references, e.g. I want to replace this:

Application.exe
Customers.dll
TelerikMenuModule.dll

with this:

Application.exe
Customers.dll
InfragisticsMenuModule.dll

and simply be able to restart the application and it runs with the new InfragisticsMenuModule.dll and does not complain that TelerikMenuModule.dll no longer exists.

+3  A: 

This is where interfaces come in. You need something like:

public interface IMenuSystem
{
    // whatever operations need to be offered by a menu system
}

Application.exe and Customers.dll may only refer to that interface. They aren't allow to know about a specific implementation.

Then you would use configuration steps (calling Register... methods or using a config file) to specify which type will provide the implementation of MenuSystem.

Daniel Earwicker
@Earwicker: but how would I implement this, e.g. how do I "call Register", I found in the Unity documentation the section "How to: Populate the Module Catalog from a Configuration File or a Directory in WPF" which I'll work through.
Edward Tanguay
Yes, that sounds like the right thing.
Daniel Earwicker
This is the right technique. In your Shell, you register an object with your container that implements IMenuSystem. "Client" modules just declare they need an IMenuSystem and your shell will inject an implementation that knows about Infragistics or knows about Telerik. You should only need each module to reference a "Contracts" DLL that just contains your interface definitions.This is the 100% correct answer. We are doing this in our own project and it works great.
Anderson Imes
+1  A: 

For obvious reason MEF comes to mind here and is designed for stuffs like this. I haven't had a chance to use Unity, so I'm not sure if it has something built in like this (i.e. scanning a directory for an IMenuModule implementation), but MEF can do this.

Suggestion also is to put this IMenuModule in a common assembly (separate from your other assembly). I usually called this thing Something.Core.dll.

So you might have: Application.exe, Customer.dll, Application.Core.dll, and your specific MenuModule implementation.

Your specific MenuModule implementation will reference the Application.Core assembly to gain access to its IMenuModule interface and implement it there.

Jimmy Chandra
that makes sense, so you are saying: (1) make Application.Core.dll with IMenuModule, (2) make InfragisticsMenuModule with "MenuModule : IMenuModule" and hard reference Application.Core.dll, and (3) in Customers.dll do a hard reference to Application.Core.dll? Any reason why you have Application.Core at all and not just put all your Interfaces in Application itself?
Edward Tanguay
It's just out of habit :). You could put it in Application itself if you want.
Jimmy Chandra
that works well until I have to register my object: container.RegisterType<IMenuManager, InfragisticsMenuManager>(new ContainerControlledLifetimeManager());, then I need to have a hard reference to the InfragisticsModule.
Edward Tanguay
That's because you are doing this in a Module. You can do this, but I wouldn't recommend it. You should make this a function of your Shell so that your Modules aren't dependent on each other.
Anderson Imes
I updated one of your other posts with a sample. Check it out. http://stackoverflow.com/questions/1152282/looking-for-prism-example-of-modules-loading-themselves-into-a-menu/1154924#1154924
Anderson Imes