An interesting topic, that I always love to discuss, is how to find a balance between building a pure domain model and being pragmatic and getting the job done. It just so happens, that getting the job done, and being able to add features to a system quickly, usually conflicts with my inner purist, who really wishes to keep my domain model and services oblivious of everything infrastructure-related.

Usually, I go for pragmatism. Not only because I’m lazy, but also because I think it’s funny to come up with solutions that accelerate development, and generally make the sun shine brighter.

Actually, this post should have been #2 in a series called “Polluting My Domain”, and this post should have been #1, because in #1 I showed how I usually use attributes to give hints to the automapper in Fluent NHibernate – e.g. [Cascade] on a relation to configure NHibernate to cascade operations across that relation, or [Indexed("ix__something")] to make that column be indexed in the database, or [Encrypted] to make that particular property be backed by an encrypting IUserType.

This post, however, will show a pragmatic, elegant and flexible way to make component registration easy in an IoC container.

Most IoC containers that I know of can be configured with XML and through some kind of more or less fluent API in code. I’ll spare you the XML, so I’ll just show a small example on Castle Windsor’s fluent API:

or you can perform multiple registrations like this:

This is all fine and dandy, but I think the fluent API becomes pretty complicated when you throw customized registrations per customer and/or environment into the mix – mostly because it will become kind of obscure which services get registered where.

Therefore, one of the first things I have put in my recent projects, have been a registration routine based on attributes. Pretty simple, and yes, it does pollute my domain services with infrastructure-related stuff, but this is a great example where I prefer pragmatism and simplicity over purity.

My most recent project has two attributes, ServiceAttribute and RegisterInAttribute that look something like this:

and then the registration code looks like this:

So, having established the current value of environment, my component registration will look like this:

– and that’s it! But the best of it is that adding services to the system now becomes a breeze – check this out – registering a concrete type, offering itself as a service:

– and here’s registering different stuff depending on the environment:

This way of registering component has proven to me several times to be a simple and nifty way of managing the differences between environments, and even differences between customers (which would require a few extensions to the example above though), still being able to add services to the system quickly.

Another benefit is that it’s pretty clear what happens, even to developers who might not be that experienced in using IoC containers. If I were the only developer on a project, I would probably prefer component registration based on conventions, but when you have a team, you sometimes need to make some things more explicit.

IoC component registration

4 thoughts on “IoC component registration

  • 2010-05-09 at 09:30
    Permalink

    Looks like a great way to setup IoC.

    I’m wondering I it could be made even simpler. Having some way of discovering components without having to call RegisterComponentsFromAssemblyOf, since you already added a reference to the assembly…

    It would be nice if the assembly could simply just offer stuff to the IoC stack.

    I know that it isen’t easy, becourse it’s hard to control when assemblies are loaded…

    Reply
  • 2010-05-09 at 11:42
    Permalink

    It could be easily implemented like NServiceBus does it, which would be something like this:


    public void AutoRegister(Environment environment)
    {
    Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll").ToList()
    .ForEach(f => AutoRegisterFromAssembly(Assembly.LoadFile(f.Name), environment);
    }

    Actually, I think I like this! Kind of MEF’y, just without the ability to recompose at runtime. This way, there’s no need to mention a type from each assembly I want to include in the auto-registration.

    Reply
  • 2010-05-09 at 13:29
    Permalink

    Did’nt think of that – thats a great solution …

    I think I’m gonna go with this in my current project – although I am considering adding a small registration-class to each assembly to do any further IoC registration and setup. Should be simple …

    Reply
  • 2010-05-09 at 21:46
    Permalink

    Yeah, actually this attribute-based approach was merely part of a greater scheme in a recent project I was involved with. In that project, we had an interface like this:

    public interface IComponentRegistrar
    {
    void PerformRegistrations(IWindsorContainer container);
    }

    – and then our auto-registration routine consisted of looking for implementations of that interface in the loaded assemblies.

    And then a couple of the implementations implemented the interface by subclassing AttributeBasedAutoComponentRegistrar<TSomeTypeFromAssemblyToScan>, which would trigger the mechanism described in the post above.

    Another implementation of IComponentRegistrar would auto-register all non-abstract types where typeof(IController).IsAssignableFrom(type) without any need for attributes.

    That approach was pretty cool I think, because then the registration strategy could differ in ways that best suited each kind of service. And then, as you mention, any further IoC registration and setup could be easily added.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: