New Source Code Drop Posted

Sep 10, 2009 at 10:29 PM

Hey everyone, just wanted to let you know that I've just finished posting a new drop of the Unity 2.0 code. Some really exciting stuff in this one. From the minor to major:

1) Optional dependencies can now be specified. Just like regular ones except that if the container cannot resolve it, you get null instead of an exception.

2) The HierarchicalLifetimeManager originally posted here in the forum has been included in the codebase. And yes, the bug about Dispose not being called has been fixed.

3) You can now pass parameters to the Resolve call, which will let you give specific values for constructor parameters or to override the value resolved for a type for that resolve call.

4) The interception extension has been radically rearchitected. The interception mechanism can now be used outside of the container, and you can use it for other things than just running call handlers. In particular, you can now use interception to add whole new interfaces to intercepted objects/classes. We've also tried to address many of the interception bugs posted here on Codeplex; we haven't quite fixed them all, but lots of them should be corrected now.

Please take a look and let us know what you think!



Sep 12, 2009 at 3:42 PM

Excellent news Chris, downloaded last night and had a look today, keep up the good work.

Sep 18, 2009 at 11:27 PM


I downloaded the new source and was trying to use the ParameterOverrides feature.
Doing something like this:

ICart cart = unityServiceLocator.GetInstance<ICart>(
    new ParameterOverrides<Cart> { { "sessionID", "test" } }

If i do the above it works, although if I do this (using the interface ICart as the constructed type for ParameterOverride), it fails:

ICart cart = unityServiceLocator.GetInstance<ICart>(
    new ParameterOverrides<ICart> { { "sessionID", "test" } }

So if i have to declare my concrete type when making the resolution, it seems I defeated the whole point of using Unity to maintain the abstraction.
Am i missing something here?


Sep 19, 2009 at 5:43 AM


No, you didn't miss anything, I did when doing the initial implementation. In the next drop (should go out Monday) the overrides feature has changed slightly so that you're not required to state the type (unless you want to) and any constructor parameter that matches the name will have the value overridden.


Sep 19, 2009 at 6:01 PM


That is good news, glad to hear it!
Will there every be a time when the constructor parameters will be able to be overrided without the need to declare the parameter name as a string?
Either be able to declare the parameter in some type safe way or ideally just be able to provide the value with no reference to the parameter name at all.
Having to declare the parameter names as strings is very fragile.
Also, are we currently able to provide complex reference types as a override parameter?

I realize this issue is not a simple one, being that none of the major DI frameworks seem to have solved this in a elegant way(at least to my knowledge).

Thanks for your work!

Sep 20, 2009 at 6:52 PM


If you can find a syntax that lets us do what you want, please let me know and I'll try to put it in. I haven't been able to come up with one. Lambdas don't work; you can't pick out a constructor parameter without like you can a property, for example. The closest thing I can think of is something along the lines of what Moq does. It'd look vaguely like this:

    new ConstructorOverride(c => new MyObject(It.IsAny<IService1>(), "my specific value here", It.IsAny<Other>(), ...));

The It.IsAny method is never actually called; it's just a marker you use when walking through the expression to say "just use whatever the container would put here".

This has a bunch of issues too. Here, we're coupled to the specific constructor; change the configuration and we've broken this line of code. And it also implies you can replace not just the parameter values but the entire constructor - I don't want to allow *that* here at all for a variety of reasons (mostly having to do with the effects on the container internals). And it's just noisy; if you have a 9-argument constructor where you want to override just one of them, you have to have 9 "It.IsAny" calls in there, which completely overwhelms the actual thing you're trying to do. And finally, I really don't want to ship a class named "It". It makes me feel icky. :-)

So, like I said, it's a hard problem and I'd love to hear suggestions. In practice, though, I don't think it's actually going to be much of a problem.

As far as your second question, there is no limitation on the objects you can pass as overrides, put whatever value you want, value type, reference type, heck, you could even do:

new ParameterOverride("database", container.Resolve<Database>("otherDatabase"))

if you wanted to.



Sep 22, 2009 at 12:02 AM

Thanks Chris,

I am going to check out the new drop soon.

The way I currently am dealing with this issue is to create factories for all types that contain non-injected parameters and then registering the factory in the container.

Then i can create a derived factory if need be.



May 8, 2010 at 10:22 AM
Edited May 9, 2010 at 12:27 AM
Why not just something like a set of these? The type parameters allow for proper specification 
of the desired constructor and strongly-type the values, and the parameter names are easily derived
from the types. You've gotta write one for each quantity of parameters, but that's a minor annoyance.
Note also that this ensures use of InjectionParameter, making the implementation safe against null values.
If it were not for the need to support null values the property type parameters would not be necessary either.
Usage is straightforward, readable and type/refactoring safe.
public static T ResolveConstruct<T, P1, P2, P3>(this IUnityContainer container, P1 p1, P2 p2, P3 p3)
   if (container == null)
      throw new ArgumentNullException("container");

   var parameters = typeof(T).GetConstructor(new Type[] { typeof(P1), typeof(P2), typeof(P3) }).GetParameters();

   return container.Resolve<T>(new ParameterOverrides 
      { parameters[0].Name, new InjectionParameter(typeof(P1), p1) },
      { parameters[1].Name, new InjectionParameter(typeof(P2), p2) },
      { parameters[2].Name, new InjectionParameter(typeof(P3), p3) }