Unity Constructor Injection Issue

Dec 14, 2009 at 1:51 PM

Hello,

I am trying to use Unity as an abstract factory but am having issues. Let's say I have an interface called ICustomProvider and that I want my clients to be able to specify via a config file the concrete class of their choosing that implements ICustomProvider.  They can do this by mapping ICustomProvider to their concrete class in the config and all my code has to do is the following :

 

 ICustomProvider customProvider = unityContainer.Resolve<ICustomProvider>();

Just what I want, using Unity as an abstract factory where I provide the interface and the client provides the concrete class. This works great assuming that their concrete class implementing ICustomProvider has only one constructor with no parameters. However, if the client implements the following :

public class ClientXProvider : ICustomProvider

   {

   private ITestClass testClass;

   public ClientXProvider()

      {

      testClass = null;

      }

   public ClientXProvider(ITestClass testClass)

      {

      this.testClass = testClass;

      }

   }

Now I have an issue; this code won't work! Given the following code :

ICustomProvider customProvider = unityContainer.Resolve<ICustomProvider>();

I would assume that Unity would do the following during resolution :

1) check the config file for ICustomProvider

2) find that there's a mapping to ClientXProvider

3) load the Type metadata for ClientXProvider

4) look for constructors with parameters

5) find that there's a constructor with ITestClass as a parameter

6) check the config file for ITestClass (for dependency injection)

7) find that there's no mapping for ITestClass

8) look for another constructor with parameters

9) cannot find any other constructors with parameters

10) create an instance of ClientXProvider via the parameterless constructor and return it to me

The problem is that it's bombing out on line 6; it complains that it can't recognize ITestClass. However, I don't want it to! If I cared about having ITestClass resolved, I would have added it to the config file, but I don't care about having it resolved yet it seems that Unity does! Does anyone know what I can do?

Regards,

Anthony

Dec 14, 2009 at 4:39 PM

I think you need to register the particular constructor you want to be used, if the default one is not correct, e.g.

unityContainer.RegisterType<ClientXProvider>(new InjectionConstructor());

(Not sure what the config file equivalent is - I only do registration in code)

Dec 14, 2009 at 7:23 PM

Your assumed sequence is incorrect. Unity's default behavior is to choose the longest constructor. It doesn't search around for one, if the longest constructor fails then it fails. If you want it to choose a different constructor, you need to tell it, either in configuration, through the API, or with an attribute.

Configuration wise, that'd look something like this to choose the zero arg constructor:

<type type="ICustomProvider" mapTo="ClientXProvider">

    <typeConfig>

        <constructor />

    </typeConfig>

</type>

 

This configuration will get a little shorter in Unity 2.0.