Simplified Autofac registrations

I’m building an application which will monitor other applications (memory usage, starting them if they crash etc.). I’m trying to stop re-inventing the wheel (ohhh it’s fun to do everything yourself) and start using other components. This time I needed an IoC container and Autofac seemed like a good match for me.

To simplify IoC registration I created an attribute which I use on all my components. In this way I don’t have to remember to register each component; it’s done with the help of the attribute.

Using the attribute without constructor parameters will register the component with all interfaces:

[Component]
class MyComponent : IConsumer<MonitorEvent>, ISomeService
{
    //[….]
}

Using the constructor will only register one interface:

[Component(typeof(ISomeService)]
class MyComponent : IConsumer<MonitorEvent>, ISomeService
{
    //[….]
}

The Autofac registration looks like this:

internal class Program
{
    public static IContainer Components { get; private set; }

    private static void Main(string[] args)
    {
        var builder = new ContainerBuilder();

        //i = interface type, c = concrete type
        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
        assemblies.Each(assembly => assembly.FindComponents((i, c) => builder.RegisterType(c).As(i).SingleInstance()));

        Components = builder.Build();
    }
}

Quite smooth, huh?

The extension methods making it possible:

public static class ComponentFinder
{
    public static void Each<T>(this IEnumerable<T> enumerable, Action<T> action)
    {
        foreach (T item in enumerable)
            action(item);
    }

    public static void FindComponents(this Assembly assembly, Action<Type, Type> action)
    {
        Type componentAttribute = typeof (ComponentAttribute);
        foreach (Type type in assembly.GetTypes())
        {
            object[] attributes = type.GetCustomAttributes(componentAttribute, false);
            if (attributes.Length == 0)
            {
                type.GetInterfaces().Each(i => action(i, type));
                continue;
            }

            foreach (object attribute in attributes)
            {
                Type interfaceType = ((ComponentAttribute) attribute).InterfaceType ?? type;
                action(interfaceType, type);
            }
        }
    }
}

Getting components is done with the resolve method:

Program.Components.Resolve<IMyService>.SendMessage("Hello world");