Child containers and object lifetimes

Mar 24, 2015 at 6:09 PM

I'm trying to use child containers to isolate instances, and I've stumbled onto this weird behavior:
class A : IA {
   public A(IB b) { }

var parent = new UnityContainer();
parent.RegisterInstance<IB>(new B("Parent"));
parent.RegisterType<IA, A>(new ContainerControlledLifetimeManager());
var child = parent.CreateChildContainer();
child.RegisterInstance<IB>(new B("Child"));

// now, IA is registered in the parent and will only be created once
// but the IB it receives completely depends on the order!
parent.Resolve<IA>(); // if this is called first, B("Parent") is used
child.Resolve<IA>(); // if this is called first, B("Child") is used
I would've liked the behavior to be deterministic, and preferably when a child container resolves a parent's container-controlled instance, that only registrations from the parent would be used (and throw an exception if none was found).

Is there any way to achieve this behavior using the current implementation (I'm using the latest 3.5 release)?

Apr 15, 2015 at 9:20 AM
It is impossible to get this behavior deterministic, and I would say this is one of the many downsides of using child containers.

Unity has two options when resolving these instances for you, but none of them are good. Since the child container has a different instance of IB, and A is registered as singleton (a.k.a. container controlled), Unity either has to:
  1. return a different instance of A in the child container or
  2. return the same instance.
Returning a different instance of A breaks the guarantee that Unity gives about always returning the same instance. On the other hand, always returning the same instance, breaks the promise of allowing instances in child containers from being changed. The designers of Unity selected option two, but both are actually bad.

My advice is to prevent using Child containers, or at least, prevent yourself from using Child containers as temporal store where registrations can be swapped. This is slow and undeterministic (as you already noticed).

Without a clear use case, it is hard to describe how to solve this (because it completely depends on context), but instead of making different registrations in the child container, try using a proxy class instead:
public class BContextProxy : IB {
    IB parent; IB child; Func<bool> useParent;
    public BContextProxy(IB parent, IB child, Func<bool> useParent) {
        this.parent = parent; this.child = child; this.useParent = useParent;

    int IB.Method1(string x) {
        var b = this.useParent() ? this.parent : this.child;
        return b.Method1(x);
You can register this proxy as singleton:
parent.RegisterInstance<IB>(new BContextProxy(
    parent: new B("Parent"),
    child: new B("Child"),
    useParent: () => /* determine is running in context of child container here */));
Apr 15, 2015 at 10:00 AM
Thanks, but I managed to solve it by resolving all the registrations in the parent context in advance.