"BuildUp" Existing Objects with StructureMap

I know, you’re plrobably sick of me clogging the CodeBetter feed with this stuff, but I needed to post this just to answer a question on the StructureMap list.  A longstanding feature request is to be able to apply setter injection of dependencies into an object that’s already constructed.  The main culprit is WebForms and other *ahem* frameworks that don’t allow you to control the construction of objects.  I resisted it for quite some time because a.) I don’t do WebForms and b.) I thought it was going to be hard. Well, enought people asked for it, I found a very good reason to use it on our app, and it turned out that it only took an hour or so to implement*, so here it is (excerpted from the StructureMap docs):

Many times you simply cannot control when an object is going to be created
(ASP.Net WebForms), but you may still want to inject dependencies and even
primitive values into an already constructed object.  To fill this gap,
StructureMap 2.5.2+ introduces the “BuildUp()” method on Container and
ObjectFactory.  BuildUp() works by finding the default Instance for the
concrete type passed into the BuildUp() method (or create a new Instance if one
does not already exist), then applying any setters from that Instance
configuration.  At this time, StructureMap does not apply interception
inside of BuildUp().

Let’s say that we have a class called “BuildTarget1″ like
this:

    public class
BuildUpTarget1

    {

        public
IGateway Gateway {
get; set; }

    }

In usage, we’d like to have the Gateway dependency injected into a new instance of the BuildTarget1 class when we call BuildUp():

        [Test]

        public
void
create_a_setter_rule_and_see_it_applied_in_BuildUp_through_ObjectFactory()

        {

           
var
theGateway = new
DefaultGateway();

           
ObjectFactory
.Initialize(x =>

            {

               
x.ForRequestedType<IGateway>().TheDefault.IsThis(theGateway);

 

               
// First we create a new Setter Injection Policy
that

               
// forces StructureMap to inject all public
properties

               
// where the PropertyType is IGateway

               
x.SetAllProperties(y =>

                {

                   
y.OfType<IGateway>();

                });

            });

 

           
// Create an instance of BuildUpTarget1

           
var
target = new
BuildUpTarget1();

 

           
// Now, call BuildUp() on target, and

           
// we should see the Gateway property assigned

           
ObjectFactory
.BuildUp(target);

 

           
target.Gateway.ShouldBeTheSameAs(theGateway);

        }

BuildUp() also works with primitive properties (but I’m not sure how useful this
will really be):

    public class
ClassThatHasConnection

    {

        public
string ConnectionString {
get; set; }

    }

 

    [TestFixture]

    public class
demo_the_BuildUp

    {

        [Test]

        public
void push_in_a_string_property()

        {

           
// There is a limitation to this.  As of StructureMap 2.5.2,

           
// you can only use the .WithProperty().EqualTo() syntax

           
// for BuildUp()

           
// SetProperty() will not work at this time.

           
var
container = new
Container(x =>

            {

               
x.ForConcreteType<ClassThatHasConnection>().Configure

                   
.WithProperty(o => o.ConnectionString).EqualTo(“connect1″);

 

            });

 

           
var
@class = new
ClassThatHasConnection();

            container.BuildUp(@class);

 

           
@class.ConnectionString.ShouldEqual(“connect1″);

        }

    }

 

How my Team Uses This

I mentioned earlier that I finally did this because I wanted to use it for my project.  We extensively use stuff in our views like:

    var dashboardUrl = ‘<%= this.ActionUrl<HomeController>(c => c.DashboardIndex()) %>’

    var consoleUrl = ‘<%= this.ActionUrl<HomeController>(c => c.Console(null)) %>’

That call in the view to ActionUrl<T>() calls into a Dovetail specific class called IUrlRegistry that “knows” what the actual url is for each controller method.  Great, but that means my views need to get at the IUrlRegistry singleton.  We started to get ObjectFactory.GetInstance<IUrlRegistry>() calls sprinkled into the base class for our views, but that’s an anti pattern.  Instead, we now use the BuildUp() function to inject a couple common services into our views.  First, I created some properties on the View base page called “Urls” and “Container”:

    public class DovetailViewPage<VIEWMODEL> : ViewPage<VIEWMODEL>, ITestablePage, IDovetailViewWithModel<VIEWMODEL>

        where VIEWMODEL : ViewModel

    {

        public DovetailViewPage()

        {

            ObjectFactory.BuildUp(this);

        }

 

        public IUrlRegistry Urls { get; set; }

        public IContainer Container { get; set; }

    }

We didn’t find a clean way to intercept the creation of WebForms objects in the MVC framework without rewriting the WebFormsEngine class completely (we’re in contact with the MVC team trying to get this relaxed a bit and get a new seam put in there), so I punted and just made a quick call to ObjectFactory.BuildUp(this) in the constructor function to force StructureMap to push in the two setters.  It’s not ideal, but it’s good enough for the moment. 

Lastly, how does StructureMap know to set those two properties, and not others?  That’s where the new setter injection policies come into play.  Inside the Registry that we use to bootstrap our MVC application we have a setter policy that just says “always inject IUrlRegistry and IContainer”:

    public class WebCoreRegistry : Registry

    {

        public WebCoreRegistry()

        {

            SetAllProperties(x =>

            {

                x.OfType<IUrlRegistry>();

                x.OfType<IContainer>();

            });

        }

    }

The “IContainer” property is just a reference to the current Container object behind ObjectFactory.

 

 

* StructureMap uses Reflection.Emit to write out the “InstanceBuilder” classes that invoke constructor functions and apply setter injection to concrete classes.  I did it that way partially to gain experience with IL generation for another project I ended up abandoning.  Frankly, emitting IL is a humongous PITA.  StructureMap 2.5 represents a near rewrite, but I left the emitting code mostly alone with just some minor cleanup.  When .Net 4.0 hits with the ability to do much more with Expressions, I’d at least like to try to replace the emitting code with Expression munging.

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 StructureMap. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://weblogs.asp.net/thangchung thangchung

    Hi Jeremy,

    This post is really good to me. I found some methods for setters injecting , and now it is become simple. I like SetAllProperties method in WebCoreRegistry, it is very amazing!

  • http://blogs.lessthandot.com chrissie1
  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @chrissie,

    Thank you for the comment *and* the blog post.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Paco:

    We haven’t hit a performance problem on that, but we haven’t done any load testing yet. You’re scaring me a little bit.

    Chad’s idea for that is to have the url’s read into constants right after app initialization. That’d largely remove that problem.

  • http://blogs.lessthandot.com chrissie1

    Thank you again for all your hard work. I made a little post about this feature. http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/structuremap-is-way-cool . I will sacrifice an animal in your name tommorow (for the animal lovers out there, an ant or a fly nothing major).

  • Paco

    Good post serie about StructureMap!

    A bit offtopic, but I wonder how you did build the IUrlRepository implementation. Does it use caching or does it use Lamba.Compile?
    I’m asking this because Html.ActionLink is Asp.Net mvc is the main bottleneck in the app I’m working on.

  • http://jimmybogard.lostechies.com Jimmy Bogard

    Thanks for this. Otherwise, we had a bunch of ObjectFactory.GetInstance calls inside our base view page class, manually setting all of the fields. That was fugly.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Travis,

    No, the setter injection policies are global, and act in all cases. It’s just that the BuildUp() will be much more useful with the combination of BuildUp + Setter Injection Policies.

    Or at least that’s my theory…

  • http://www.heliosfx.com Travis

    Thank you for this. So the “setter injection policies” only come in to play when BuildUp() is called?

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    The “FM” is less than a week old, so I’ll make some allowances ;)

  • http://http:blogs.lessthandot.com Christiaan Baes

    Cool. This will come in handy to inject stuff in winforms usercontrols and keep the designer happy and usable at the same time.

    Perhaps I should read the rest of the FM.