I’m developing an application where a great deal of the functionality will be provided through plug in assemblies dropped into the main installation folder. This application is using Ninject as the dependency injection framework, and Caliburn.Micro for its support of the MVVM architecture.

Fortunately, making these two frameworks cooperate is pretty easy - all you have to do is to create a custom Caliburn.Micro bootstrapper to tie them together. Here’s mine, with some explanation about how it works interspersed.

public class AppBootstrapper : Bootstrapper<IShell>
{        
    protected override void Configure()
    {
        mKernel = new StandardKernel();
        mKernel.Load(Assembly.GetExecutingAssembly());
        mKernel.Load("*.dll");

The Load() method loads all the assemblies in the same directory as the main application and automatically registers any public classes implementing INinjectModule.

Tip: Test to see if a module is being loaded by putting a breakpoint in it’s Load() method. Use DebuggerBreak() if you can’t do this in the IDE. If the module isn’t being loaded, double check that it’s public.

    var assemblies 
        = mKernel.GetModules()
            .Select(m => m.GetType().Assembly)
            .Distinct()
            .ToList();
    AssemblySource.Instance.AddRange(assemblies);
}

When Caliburn.Micro looks for a View to display for a given ViewModel, it does not scan all loaded assemblies, but only those listed by the AssemblySource. If we want the Views in our plug in assemblies to be found, we need to add them to this list.

For simplicity, I assume that every assembly containing Views will also have a Ninject module. This allows me to reuse the plugin discovery already performed by the Load() call above by taking all the loaded modules, finding their original assembly and using them for Caliburn.Micro.

Tip: If your View isn’t being found by Caliburn.Micro and its declared in some other assembly - not the entry point of your application - make sure your bootstrapper adds the appropriate assembly to the module.

Once our module discovery and assembly registration steps are complete, the rest of the bootstrapped is nearly trivial.

    protected override object 
        GetInstance(Type serviceType, string key)
    {
        return mKernel.Get(serviceType, key);
    }

    protected override IEnumerable<object>
        GetAllInstances(Type serviceType)
    {
        return mKernel.GetAll(serviceType);
    }

    private IKernel mKernel;
}

Comments

blog comments powered by Disqus
Next Post
The Unwanted WCF Service Host  15 Feb 2012
Prior Post
When a bomb beheld  24 Jan 2012
Related Posts
Browsers and WSL  31 Mar 2024
Factory methods and functions  05 Mar 2023
Using Constructors  27 Feb 2023
An Inconvenient API  18 Feb 2023
Method Archetypes  11 Sep 2022
A bash puzzle, solved  02 Jul 2022
A bash puzzle  25 Jun 2022
Improve your troubleshooting by aggregating errors  11 Jun 2022
Improve your troubleshooting by wrapping errors  28 May 2022
Keep your promises  14 May 2022
Archives
January 2012
2012