StaticFactoryExtension and child containers does not play well together

Apr 28, 2009 at 10:20 AM

I have registered a component in a container using a factory method. When resolving this component in a child container I expected that the argument passed to the factory delegate would be the child container but it isn't. After checking the code it is pretty obvious that the container parameter is bound at registration time. I.e. in RegisterFactory<>:

 FactoryBuildPlanDelegate planDelegate = delegate { return factoryMethod(Container); };

Here is a test illustrating the problem:

        public void Should_get_child_container_as_parameter_when_resolving_component_using_static_factory_method() {
            IUnityContainer parent = new UnityContainer();
            parent.Configure<StaticFactoryExtension>().RegisterFactory<object>(c => c);

            IUnityContainer child = parent.CreateChildContainer();
            object containerAsObject = child.Resolve<object>();
            Assert.AreSame(child, containerAsObject);

I looked at the source but I have no idea how this could be fixed.

Greets, Andreas
Apr 30, 2009 at 8:24 AM
This is a problem I've been aware of for a while, but hasn't bubbled up high enough to fix yet. It'll be fixed in V2.0.

The fix is to actually resolve the container rather than to have that variable bound in the closure. It's one or two lines of code, but it's late and I don't remember exactly what it is right now.

Apr 30, 2009 at 8:32 AM
I tried it real quick but didn't get it to work. I.e. I modified the test above from:

            parent.Configure<StaticFactoryExtension>().RegisterFactory<object>(c => c);


            parent.Configure<StaticFactoryExtension>().RegisterFactory<object>(c => c.Resolve<IUnityContainer>());

but I still get the parent container in my test.

Apr 30, 2009 at 5:51 PM
Sorry, that's not what I meant; I need to stop posting late at night, I'm obviously not writing clearly enough.

The fix is inside the static factory extension itself. There's a couple of changes that need to happen. First, the file FactoryDelegateBuildPlanPolicy needs to become this:

internal delegate object FactoryBuildPlanDelegate(IUnityContainer container);

class FactoryDelegateBuildPlanPolicy : IBuildPlanPolicy
    private FactoryBuildPlanDelegate factory;

    public FactoryDelegateBuildPlanPolicy(FactoryBuildPlanDelegate factory)
        this.factory = factory;

    public void BuildUp(IBuilderContext context)
        if(context.Existing == null)
            IUnityContainer currentContainer = BuilderContext.NewBuildUp<IUnityContainer>(context);
            context.Existing = factory(currentContainer);

In the StaticFactoryExtension.RegisterFactory method, replace:

FactoryBuildPlanDelegate planDelegate = delegate { return factoryMethod(Container); };


FactoryBuildPlanDelegate planDelegate = delegate(IUnityContainer container) { return factoryMethod(container); };

That should do the trick. I haven't actually tried this yet, but it should work.