Configuring dependencies' dependencies with StructureMap 2.5.1 [.NET,C#]

To date I’ve generally only used the most basic of StructureMap’s configuration options. Stuff like init.ForRequestedType<SomeInterface>().TheDefaultIsConcreteType<SomeImplementor>(). But I recently needed to resolve two types which needed different configurations of the same dependency type. Here is how I got it to work, but be aware that I’m a StructureMap newbie so there might be better ways of doing this.

A contrived example

Say we have two types that both require an IController:

public class HelloView {
    public HelloView(IController controller) {}
}

public class HowdyView {
    public HowdyView(IController controller) {}
}

Our IController implementation requires an IStuffDoer:

public class Controller : IController {
    public Controller(IStuffDoer stuffDoer) {}
}

Finally, we have two IStuffDoer implementations:

    public class SayHelloWorldDoer : IStuffDoer {}
    public class SayHowdyWorldDoer : IStuffDoer {}

Configuration using StructureMap

Now we want our HelloView to have a Controller configured with a SayHelloWorldDoer, while our HowdyView controller needs a SayHowdyWorldDoer. Now this is obviously a silly, contrived example, but some semi-decent reasons to do something like this could be configuring an enumerable of Specification instances, or passing through different pipelines to change behaviour of dependencies. For now let’s try and wire up our silly example:

public class Bootstrapper {
    public static void WireUpApplication() {
        ObjectFactory.Initialize(init => {
            init.ForConcreteType<HelloView>()
                .Configure.CtorDependency<IController>().Is(
                    x => x.OfConcreteType<Controller>().CtorDependency<IStuffDoer>().Is<SayHelloWorldDoer>()
                 );
            init.ForConcreteType<HowdyView>()
                .Configure.CtorDependency<IController>().Is(
                    x => x.OfConcreteType<Controller>().CtorDependency<IStuffDoer>().Is<SayHowdyWorldDoer>()
                 );
        }
        );
    }
}

Now when we try and resolve a HelloView with a call to ObjectFactory.GetInstance<HelloView>(), StructureMap will inject a Controller configured with a SayHelloWorldDoer for it’s IStuffDoer.

Another way to do this is with named instances in StructureMap, but I think the approach above reads reasonably neatly and reveals our intent. It’s also worth pointing out that if our wireup logic becomes particularly complicated we may be better off moving parts of it into a factory or builder.

Comments