Spring loading your IoC Container

Ayende has a post up this morning called Inverting Inversion of Control where he talks about registering services with an IoC container at runtime.  Ayende is specifically saying that this technique is useful for injecting services that you either can’t control the creation of or simply want to construct in another way.  It’s funny that he should post this today because I’ve been using this technique quite a bit the last couple months in my WinForms development.  I’m breaking open the StructureMap code to start a new release today largely to add a bit more support for this scenario.  To add to the discussion, I’ll throw out an example of what I’m doing.

 

Registering pieces of the ApplicationShell

In StoryTeller and a couple of my applications at work the ApplicationShell (main form) has grown large and complicated.  It’s become advantageous to treat various parts of the main form as separate services of the user interface and let all of them be driven by separate Presenters.  For the sake of consistency with the rest of the application and avoiding nasty Law of Demeter violations, I inject these little pieces of the main form into StructureMap so that StructureMap can instantiate other services that depend on these pieces through constructor arguments.  I could create all of these little user controls and TreeNode’s via StructureMap and then call methods to attach them into the ApplicationShell later, but that quickly led to bootstrapping spaghetti code left and right.  It turned out to be much cleaner to use the design time support to place the children controls onto the ApplicationShell form, inject these children into StructureMap, and let StructureMap completely setup the Presenters that depend on these child controls through their constructors.

When I start up StoryTeller the first thing that I do is bootstrap StructureMap’s configuration.  The second thing I do is create the main ApplicationShell form.  After the child In the constructor function of ApplicationShell I call the method below to register some of the child controls of ApplicationShell into StructureMap:

        private void loadShellPartsIntoStructureMap()
        {
            ObjectFactory.InjectStub(typeof (IApplicationShell), this);
            ObjectFactory.InjectStub(typeof (IContentPanel), contentPanel);
            ObjectFactory.InjectStub(typeof (IHierarchyNode), hierarchyExplorer.HierarchyNode);
            ObjectFactory.InjectStub(typeof (IFixtureExplorerView), fixtureExplorer);
        }

The “InjectStub()” method was originally put into StructureMap to allow you to override normal StructureMap behavior to push in stubs instead of the normal service during testing.  It does also function correctly in this scenario (in the forthcoming 2.1 version I’m going to add a new method called Inject<T>(T service) ).   Regardless of any other prior configuration, StructureMap will always return the instance passed into InjectStub(Type, object) whenever an instance of the specified Type is requested.  When any other class requests IContentPanel directly or through a constructor function, the “contentPanel” child of ApplicationShell will always be returned.

Now, moving on to see how this works.  I generally use an ApplicationController class to govern the activation and deactivation of screens in the user interface.  The ApplicationController in StoryTeller has a dependency on both the IContentPanel (the tabbing container for screens) and the IHiearchyNode (the top most TreeNode in the navigation tree).  Since we’ve already injected the two little children into StructureMap, we can completely set up ApplicationController through its constructor.

        public ApplicationController(
            ICommandExecutor executor, 
            IContentPanel panel, 
            IProjectRepository repository,
            ITestEventPublisher publisher, 
            IHierarchyNode hierarchyNode)
        {
            _executor = executor;
            _panel = panel;
            _repository = repository;
            _publisher = publisher;
            _hierarchyNode = hierarchyNode;
        }
 

As long as I create ApplicationController after the StructureMap bootstrapping and the creation of ApplicationShell, I’m ready to go.  Before I switched to the path of injecting the child controls into StructureMap I had a lot more one off bootstrapping code to push around the IContentPanel and IHiearchyNode controls.  By refactoring to the “injected children” mode I cut back on a lot of undesirable coupling and trimmed down some chatty interfaces. 

One of my little maxims of programming is to strive to put everything a class needs into a constructor so that we know the class is ready to go as soon as it’s created.  This little trick of spring loading the UI controls into the IoC container gets us closer to that ideal.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in StoryTeller, StructureMap. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • SteveG

    Glad to see you mention the Law of Demeter – I would rather create specific menthod calls than expose the underlying dependency object.

  • Weex

    Hi,

    that link http://storyteller.tigris.org/svn/storyteller/trunk/src/StoryTeller.UserInterface/ApplicationController.cs
    won’t open. It requires some credentials for read access. Could you please change that? So, that curious readers could see what you’ve linked to :)

  • http://www.ikriv.com/ Ivan Krivyakov

    I remember struggling with Spring and command-line arguments. Creation (or non-creation) of some things dependent on the command line arguments, and I could not find away to “inject” them into the framework. I ended up using hand-written factories.

    If I had Inject, this would have solved the problem.