Thursday, October 07, 2010

Experimental ASP.NET MVC Add-ins : Updated (or why it pays to blog)

Get the code here.

Github is awesome. Yesterday I wrote a post on how to use MEF alongside Windsor to build an add-in framework for a website. Today Krzysztof Koźmic took my MefAreas and removed all the MEF code. Why? Well, it turns out that a new feature in Windsor 2.5 is dynamic assembly loading and registration. It’s really nice, and is a far better solution that my nasty MEF/Windsor hack.

Here’s what the startup code used to look like:

public class MvcApplication : HttpApplication, IContainerAccessor
{
    ...

    protected void Application_Start()
    {
        HostingEnvironment.RegisterVirtualPathProvider(new AssemblyResourceVirtualPathProvider());
        RegisterRoutes(RouteTable.Routes);

        InitializeWindsor();
        InitializeAddins();
    }


    void InitializeAddins()
    {
        using (var mefContainer = new CompositionContainer(new DirectoryCatalog(HttpRuntime.BinDirectory, "*AddIn.dll")))
        {
            var lazyInstallers = mefContainer.GetExports<IAddinInstaller>();
            foreach (var lazyInstaller in lazyInstallers)
            {
                var installer = lazyInstaller.Value;
                Container.Install(new CommonComponentInstaller(installer.GetType().Assembly));
                installer.DoRegistration(Container);
            }
        }
    }

    void InitializeWindsor()
    {
        container = new WindsorContainer()
            .Install(new CoreComponentsInstaller())
            .Install(new AddinInstaller(Assembly.GetExecutingAssembly()));

        var controllerFactory = Container.Resolve<IControllerFactory>();
        ControllerBuilder.Current.SetControllerFactory(controllerFactory);
    }

    static IWindsorContainer container;
    
    public IWindsorContainer Container
    {
        get { return container; }
    }
}

And here’s what it looks like now:

public class MvcApplication : HttpApplication, IContainerAccessor
{
    ...

    protected void Application_Start()
    {
        HostingEnvironment.RegisterVirtualPathProvider(new AssemblyResourceVirtualPathProvider());
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        InitializeWindsor();
    }

    void InitializeWindsor()
    {
        container = new WindsorContainer()
            .Install(FromAssembly.This(),
                     FromAssembly.InDirectory(new AssemblyFilter(HttpRuntime.BinDirectory, "*AddIn.dll")));

        var controllerFactory = Container.Resolve<IControllerFactory>();
        ControllerBuilder.Current.SetControllerFactory(controllerFactory);
    }

    static IWindsorContainer container;
    
    public IWindsorContainer Container
    {
        get { return container; }
    }
}

Install(FromAssembly.InDirectory(new AssemblyFilter(HttpRuntime.BinDirectory, “*AddIn.dll”)) does the magic of loading all assemblies with file names ending in ‘AddIn.dll’ and grabbing their IWindsorInstallers. No need for MEF, no need for IAddinInstaller.

Once again a real vindication of why it pays to share. Thanks Krzysztof!

1 comment:

Victor said...

Thanks for posting! This looks very exciting. I've been playing around with portable areas for mvc contrib but this looks like a nice alternative.