Simplified autofac registrations

I’m building an application which will monitor other applications (memory using, start 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 a 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 by the help of the attribute.

Using the attribute without constructor parameters will register the component with all interfaces.
[sourcecode language=”csharp”]
[Component]
class MyComponent : IConsumer<MonitorEvent>, ISomeService
{
//[….]
}
[/sourcecode]

While using the constructor will only register one interface.
[sourcecode language=”csharp”]
[Component(typeof(ISomeService)]
class MyComponent : IConsumer<MonitorEvent>, ISomeService
{
//[….]
}
[/sourcecode]

The autofac registration looks like this:
[sourcecode language=”csharp”]
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();
}
}
[/sourcecode]

Quite smooth, huh?

Extension methods making it possible:
[sourcecode language=”csharp”]
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);
}
}
}
}
[/sourcecode]

Getting components is done by the resolve method:
[sourcecode language=”csharp”]
Program.Components.Resolve<IMyService>.SendMessage("Hello world");
[/sourcecode]