Use Cases Not Covered by Current Xml Configuration Schema

Feb 16, 2008 at 8:10 PM
Edited Feb 16, 2008 at 8:17 PM
I think that we should see about supporting an additional level of expressiveness to the Unity configuration that allows us to pick out the constructor we want to use for our types in the container.

Currently we have support for this:

<unity>
<containers Default="containerOne">
<container name="containerOne">
<types>
<add name="MyType1" type="Custom.MyBaseClass"
mapTo="Custom.MyConcreteClass" />

Which i think is just great. By default Unity is built around the use case for types that have a single constructor. If multiple are available, unity is going to take the first ConstructorInfo that comes out of Type.GetConstructors() array. To allow us to deterministically use a specific constructor we can decorate the constructor in question with an attribute. Which is also fine and dandy for many use cases. However it lacks some of the flexibility that I think many of us would like to see. There's three specific use cases where I can think this is really needed:

1. 3rd party code or existing libraries with classes that have many constructors and doesn't know anything about Unity. To accomplish this use case today we'd probably resort to a factory object with a default or single parameterized constructor that had a method to build up the other class. Get's the job done easily and franky does the trick without too much effort but I really hate to have two ways to build up objects instead of Unity being a one stop shop (or bettern put, I hate to resort to two stage construction if I don't need to). It's can also be inpractical or impossible to modify the code to put that attribute on the constructor we want (for instance we don't have it/own the code in question).

2. I don't always know what constructor I want at compile time. Many times it is specific to the deployment and therefore not determined until configuration time of an application. This is a use case we've run into very specifically with the Microsoft.Uddi.UddiConnection class. There's 4 constructors available and sometimes I need to pick one or the other depending on the deployment scenario. Specifically I may need to use user name and password authentication in one deployment and in another I can use Windows auth. I don't technically own the code to slap the attribute on it so how do we handle that situation without resorting to Unity providing access to a UddiFactory class that has calls a specific constructor for me and swap out configurations?

3. Many times we want to enable adhoc decorations on types that we build up. I tend to see this needed in applications, generally server side, that utilize a Command Orientated Interface (a pattern I find lends itself naturally to implementing services). Now I know we can write an extension that incorporates this using Policy Injection Block but sometimes that really a huge overkill for what we need. Let me use Martin Fowler's example on Decorate Commands http://www.martinfowler.com/bliki/DecoratedCommand.html and postulate that the CommandDecorator class in his example has a protected constructor that accepts an instance of Command not any specific type of command (in order to promote reuse). In addition, the CommandDecorator class sub classes Command thereby exposing the same interface. The concrete implentation of a some CommandDecorator does whatever it needs to do (say create an ambient transaction) and then calls the inner command's execute method. That inner command may or may not be another decorator. Because all the types involved here expose a single constructor that accepts a single parameter typed as Command, how does Unity know what type of command to build up? If I could select the constructor and actually state the concrete type i wanted at configuration time then we're in business. Wouldn't Unity by default end up in a infinite recursion situation (or does it recoginze this situation and jsut give up?) trying to follow the type mapping on CommandDecorator class to TransactionDecoratorCommand class that has a dependency on CommandDecorator that type maps to TransactionDecoratorCommand and so forth ad infinitum. How do we express that situation in configuration schema that Unity uses? I know how to accompish this in code with Unity but not how your config can.

So I question if this is a way to approach this configuration issue to support the above outlined use cases

Use case #1/2
Here's a place where I am stating I want to use the specific constructor that accepts a single string vs the other one that uses the same string and an Enum
<unity>
<containers Default="containerOne">
<container name="containerOne">
<types>
<add name="MyType1" type="TypeWithManyConstructors">
<!-- you would only use one of these constructor elements. they're included for suscinctness-->
<constructor>
<!-- Find Constructor with a single parameter of string-->
<param type="System.String">
<ValueParameter>My Value but one I don't to use as an instance.</ValueParameter>
</param>
</constructor>

<!-- variation 2 -->
<constructor>
<!-- Find Constructor with a parameter of string-->
<param type="System.String">
<LookupParameter Name="my instance name"><!--My Value but one that IS defined as an instance because I use it in several types and I don't want to retype the smae value over and over--></LookupParameter>
</param>
</constructor>
</add>
</types>
</container>
</containers>
</unity>

Use case #3
<unity>
<containers Default="containerOne">
<container name="containerOne">
<types>
<add name="Our Command" type="InterestingCommand"/>
<add name="Transaction Decorator" type="TransactionDecoratorCommand">
<constructor>
<!-- find constructor that accepts Command as parameter -->
<param type="Command">
<!-- satisfy the parameter by finding the element matching add@name = type@name -->
<DependencyParameter name="Our Command"/>
</param>
<constructor>
</add>
<add name="Security Decorator" type="Command" mapTo="SecurityDecoratorCommand">
<constructor>
<!-- find constructor that accepts Command as parameter -->
<param type="Command">
<!-- this time we'll satisfy the parameter by finding explicitly declaring the type -->
<DependencyParameter type="TransactionDecoratorCommand"/>
</param>
</constructor>
</add>
</types>
</container>
<containers>
</unity>

This syntax is not disimilar to an approach we've taken in a container we built when EntLib 3.0 first came out to automatically wire up components with dependency chains. Worse case my team and I are thinking we'll provide an alternative configuration syntax based on our current DI container (has a very unity like interface over Object Builder as well so it's gonna be a quick port) to enable this. Not disimilar to the whole nano/pico container arrangement. We've just got to get permission from our IP owner to release the code under the appropriate license.

Community thoughts/Cheers/Flames/Jimmy gets ejected out of another airlock/Am I smoking Crack?

-JZ
Feb 17, 2008 at 12:15 AM
First, just to clarify something regarding the ctor selection: When no InjectionConstructorAttribute is specified, it doesn't take the 1st ctor, it takes the one with the most arguments (at least as I can see in the current code base).

Second, I totally agree for better config support. But there are changes to be made to the container in order to support such config. AFAIK, there are no ways to provide values that aren't registered as dependencies nor instances in the container.

So if I have a class with the following ctor:

public class Foo
{
  public Foo(string name, int index) {...}
}

I need to register 2 instances in the container which make no sense since registering instances should be for shared services not for parameters local to a type ctor.

Just imagine I need to build a second type through the container:

public class Person
{
  public Person(string firstName, string lastName) {...}
}

How are we supposed to build such types?
Feb 17, 2008 at 3:25 PM
Yes, Francois is correct - the container uses the greediest constructor, unless it finds the explicitely decorated one.
Re: config scheme improvement - sure, this is something we'll consider and likely do. Thanks for the good feedback!
Feb 17, 2008 at 4:28 PM


gmelnik wrote:
the container uses the greediest constructor

thanks for the heads up. :) I'm glad the larger of the cocnstructors is taken by default.

Since that's the case you'll want to update the documentation in the "Annotating Objects for Constructor Injection" article
There it states:

How Unity Resolves Target Constructors and Parameters
When a target class contains more than one constructor, Unity will use the one you decorate with the InjectionConstructor attribute. If there is more than one constructor, and none carries the InjectionConstructor attribute, Unity will use the first one returned through reflection over the class members. Reflection occurs in an effectively random order, and so the selected constructor may not be the first within the class declaration.


:)
Feb 17, 2008 at 4:30 PM
I had already created a WI on this: http://www.codeplex.com/unity/WorkItem/View.aspx?WorkItemId=1355