Castle Windsor lazy loading

I just committed a very cool feature to Castle Windsor/MicroKernel that adds lazy registration capabilities. By lazy registration I mean – you get a chance to register a component right at the spot when it’s about to be resolved.

This enables things like integration with external sources of components, like MEF, or WCF config files, lets you distribute your registration in time so that you don’t have to do all of it upfront and many more.

Behind all of this, is this interface:

/// <summary>
/// Provides lazy registration capabilities to the container.
/// </summary>
/// <remarks>
/// When a component is requested from a container, that has not been registered
/// container loads up all the implementers of this interface and asks them in turn
/// whethere they can provide that component, until it finds one that will.
/// </remarks>
public interface ILazyComponentLoader
{
    /// <summary>
    /// Used by container to allow the loader register component for given <paramref name="key"/> 
    /// and <paramref name="service"/> to the container at the time when it is requested
    /// </summary>
    /// <param name="key">Key of the requested component or null</param>
    /// <param name="service">Type of requested service or null</param>
    /// <returns>Registration that registers component for given key and/or service or null.</returns>
    /// <remarks>
    /// While both key and service can be null reference it is guaranteed that at least one of them will not be null.
    /// When implementer opts in to provide the requested component (by returning not-null registration) it is required
    /// to register component for requested key/service combination (when one of the elements is null, it should be ignored as well).
    /// When implementer does not want to register the requested component it nust return null.
    /// </remarks>
    IRegistration Load(string key, Type service);
}

You can now use it pretty easily, as I will show in a second. Let’s take a trivial example:

[DefaultImplementation(typeof(Implementation))]
public interface IHasDefaultImplementation
{
    void Foo();
}
 
public class Implementation : IHasDefaultImplementation
{
    public void Foo()
    {
        
    }
}

We have an interface, a class that implements it, and an attribute we put on the interface that points to its default implementation (assuming we have many). This example is completely artificial, but that’s not the point.

We still need some implementation of ILazyComponentLoader, that will work with this scenario.

public class Loader : ILazyComponentLoader
{
 
    public IRegistration Load(string key, Type service)
    {
        if (!Attribute.IsDefined(service, typeof(DefaultImplementationAttribute)))
        {
            return null;
        }
 
        var attributes = service.GetCustomAttributes(typeof(DefaultImplementationAttribute), false);
        var attribute = attributes[0] as DefaultImplementationAttribute;
        return Component.For(service).ImplementedBy(attribute.Implementation).Named(key);
    }
}

Our Loader is called by the container when a component is requested, that has not been registered in the container. We then check if type of the service requested has DefaultImplementationAttribute, and if it does we register the component with the default implementation, which then will be resolved.

To wire our loader with the container, we register it with ILazyComponentLoader service just like any other component. Yeah – no additional API to memorize!

var kernel = new DefaultKernel();
kernel.AddComponent<Loader>(typeof(ILazyComponentLoader));

That’s all we need to make this test pass:

[Test]
public void Can_Lazily_resolve_component()
{
 
    var service = kernel.Resolve("foo", typeof(IHasDefaultImplementation));
    Assert.IsNotNull(service);
    Assert.IsInstanceOf<Implementation>(service);
}

The code is available now in the trunk, and you can get latest binaries here.

Technorati Tags:

Posted 11-16-2009 12:00 AM by Krzysztof Koźmic
Filed under:

[Advertisement]

Comments

Glenn Block wrote re: Castle Windsor lazy loading
on 12-25-2009 6:32 PM

Nice job Krzys! So does this mean we'll see Windsor accepting a catalog in it's construction soon?

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)