Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Register type with Unity to use constructor requiring parameter array

Given the following constructor signature:

public MyClass(Class1 arg1, params Class2[] arg2)

How can I register MyClass with Unity passing in specific named types using an InjectionConstructor.

I've tried the following:

unityContainer.RegisterType<IMyClass, MyClass>(new InjectionConstructor(typeof(Class1), new ResolvedParameter<IClass2>("name1"), new ResolvedParameter<IClass2>("name2")))

but get an exception saying that there is no constructor with signature:

public MyClass(Class1 arg1, Class2 arg2, Class2 arg3)

I have got round the problem by overloading the MyClass constructor. Is there any way to do this without overloading the constructor?

like image 248
macleojw Avatar asked Dec 07 '12 12:12

macleojw


1 Answers

Why would you try and use an InjectionConstructor in the first place? Unity knows how to handle arrays out of the box.

The params keyword is just some syntactic sugar for the compiler. Under the cover args2 is just a simple array.

[TestMethod]
public void TestMethod1()
{
  var container = new UnityContainer();
  // if you absolutely have to use an InjectionConstructor this should do the trick
  // container.RegisterType<IMyClass, MyClass>(
  //   new InjectionConstructor(typeof(Class1), typeof(Class2[])));
  container.RegisterType<IMyClass, MyClass>(
    new InjectionConstructor(typeof(Class1), typeof(Class2[])));
  container.RegisterType<Class2>("1");
  container.RegisterType<Class2>("2");
  container.RegisterType<Class2>("3");
  var myClass = container.Resolve<IMyClass>() as MyClass;
  Assert.IsNotNull(myClass);
  Assert.IsNotNull(myClass.Arg2);
  Assert.AreEqual(3, myClass.Arg2.Length);
}

interface IMyClass
{
}
class MyClass : IMyClass
{
  public Class1 Arg1 { get; set; }
  public Class2[] Arg2 { get; set; }
  public MyClass(Class1 arg1, params Class2[] arg2)
  {
    Arg1 = arg1;
    Arg2 = arg2;
  }
}
class Class1
{
}
class Class2
{
}

Update

If you are only using some of the named registrations you will have to use the ResolvedArrayParameter.

container.RegisterType<IMyClass, MyClass>(
  new InjectionConstructor(
    typeof(Class1),
    new ResolvedArrayParameter<Class2>(
      new ResolvedParameter<Class2>("1"), 
      new ResolvedParameter<Class2>("2"))));

Brrr! This is super ugly but it should solve your problem.

like image 172
Sebastian Weber Avatar answered Oct 22 '22 17:10

Sebastian Weber