Allowing the Simple Injector to resolve arrays and other list types

The default behavior of the Simple Injector is to resolve collections of types through the IEnumerable<T> interface. Resolving a set of elements using other collection types is possible by registrering a mapping on a per type basis, such as can be seen the following example:

container.RegisterAll<IFilter>(
    typeof(SqlFilter), typeof(XssFilter), typeof(SmartFilter));

container.Register<IFilter[]>(
    () => container.GetAllInstances<IFilter>().ToArray());
When having many collections of types that need to be resolved in this way, the registration can be come cumbersome. Alternatively you can revert to unregistered type resolution, as can be seen in the following example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

using SimpleInjector;

public static class CollectionRegistrationExtensions
{
    public static void AllowToResolveArraysAndLists(
        this Container container)
    {
        container.ResolveUnregisteredType += (sender, e) =>
        {
            var serviceType = e.UnregisteredServiceType;

            if (serviceType.IsArray)
            {
                RegisterArrayResolver(e, container, 
                    serviceType.GetElementType());
            }
            else if (serviceType.IsGenericType &&
                serviceType.GetGenericTypeDefinition() == typeof(IList<>))
            {
                RegisterArrayResolver(e, container, 
                    serviceType.GetGenericArguments()[0]);
            }
        };
    }

    private static void RegisterArrayResolver(UnregisteredTypeEventArgs e, 
        Container container, Type elementType)
    {
        var producer = container.GetRegistration(typeof(IEnumerable<>)
            .MakeGenericType(elementType));
        var enumerableExpression = producer.BuildExpression();
        var arrayMethod = typeof(Enumerable).GetMethod("ToArray")
            .MakeGenericMethod(elementType);
        var arrayExpression = 
            Expression.Call(arrayMethod, enumerableExpression);

        e.Register(arrayExpression);
    }
}
After copying the previous code snippet to your project, you can allow mapping of array and IList<T> types to IEnumerable<T> for all registered collections, with the following lines:

container.AllowToResolveArraysAndLists();

Last edited Feb 20, 2013 at 7:48 PM by dot_NET_Junkie, version 7