6

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?

2 Answers 2

6

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I'm using an injection constructor because I have several implementations of IClass2 and I'm only passing some of them to the MyClass constructor. If there is a better way to do this please tell me!
1

Since it seems to dislike the 'Class2' instances simply being listed directly, is it possible that explicitly setting them into an array (and therefore explicitly matching the constructor signature of Class1, Class2[]) would work:

unityContainer.RegisterType<IMyClass, MyClass>(new InjectionConstructor(typeof(Class1), new Class2[]{new ResolvedParameter<IClass2>("name1"), new ResolvedParameter<IClass2>("name2")}))

1 Comment

I'm afraid that doesn't work because the array is being declared of type Class2, but the objects it's being initialised with are of type ResolvedParameter. If I remove the object type from the array definition (i.e. new [] {...}) then it looks for a constructor taking in an array of ResolvedParameters!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.