Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Simplified autofac Registrations

5.00/5 (1 vote)
28 Oct 2010LGPL3 14.2K  
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 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.

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

While using the constructor will only register one interface.

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

The autofac registration looks like this:

C#
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?

Extension methods making it possible:

C#
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 by the resolve method:

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

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)