How to automatically inject all named instances into a generic array?

Feb 13, 2014 at 11:07 PM
Edited Feb 13, 2014 at 11:08 PM
Hi
public class Account { }

public class MyClass<T>
{
    public T[] injectedValue;

    public MyClass(T[] injectedValue)
    {
        this.InjectedValue = injectedValue;
    }
}
MyClass<> has a single constructor, so the following will resolve all named registrations of Account type and place them into a generic array:
    container.RegisterType<Account>("first");
    container.RegisterInstance<Account>("second", new Account());

    var myClass = container.Resolve<MyClass<Account>>();
    Console.WriteLine(myClass.InjectedValue.Length);   // 2
But how do we tell Unity to resolve all named registrations of Account type and place them into a generic array when MyClass<> has several constructors:
public class MyClass<T>
{
    public T[] injectedValue;

    public MyClass() { }

    public MyClass(T[] injectedValue)
    {
        this.InjectedValue = injectedValue;
    }
}
btw, I'm aware that we could manually specify which instances to inject into array using GenericResolvedArrayParameter:
container.RegisterType(
    typeof(MyClass<>),  
    new InjectionConstructor(
        new GenericResolvedArrayParameter(
            "T",
            new GenericParameter("T", "first"),
            new GenericParameter("T", "second"))));
thanks
Feb 15, 2014 at 7:33 AM
First you need to register the array instances (as in your code sample):
container.RegisterType<Account>("first");
container.RegisterInstance<Account>("second", new Account());

Now because in your example the constructor you want is the one with the most arguments you can just do a regular register and resolve:
container.RegisterType(typeof(MyClass<>));

var myClass = container.Resolve<MyClass<Account>>();

And it should just work. "But wait", you're saying, "that's a bit of a cheat since what I really want to know is how to explicitly specify the generic array constructor".

OK, you got me on that one. So let's assume we have a slightly different MyClass:
public class MyClass<T>
{
    public T[] injectedValue;

    public MyClass() { }

    public MyClass(T[] injectedValue)
    {
        this.injectedValue = injectedValue;
    }

    public MyClass(string name, int age)
    {
    }
}

Now that we have another constructor with 2 parameters we can't rely on Unity to pick the "right" constructor (assuming we really want to inject the array) since it will pick the constructor with name and age because it has the most parameters.

In that case we can register as follows:
Type t = typeof (MyClass<>).GetGenericArguments()[0].MakeArrayType();
container.RegisterType(typeof(MyClass<>), new InjectionConstructor(t));

var myClass = container.Resolve<MyClass<Account>>();

Now when resolving Unity will pick the Array of T constructor and inject all named registered instance of Type T.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Feb 16, 2014 at 8:54 PM
I completely forgot that Unity calls a constructor with most parameters

Anyways, thank you for your help