A Gentle Quickstart for StructureMap 2.5

The most general question I get with StructureMap is “how do I get started?”  Personally, I’d recommend that you first get comfortable with some concepts and the basic patterns of Dependency Injection and Inversion of Control first.  Assuming that you’re already familiar with those concepts, or you’d really rather skip the pedantry and jump right into concrete code, the first thing to do is go download StructureMap and jump into usage (then come back to the patterns and pedantry). 

Some Salient Facts:

  • The latest release is 2.5.0.0, available for download on SourceForge at http://sourceforge.net/projects/structuremap
    • The only DLL that you need for doing basic Service Locator and/or Dependency Injection is the StructureMap.DLL file.
  • There is a google group for StructureMap support at http://groups.google.com/group/structuremap-users?hl=en
  • StructureMap is released under the Apache 2.0 license, meaning that you can use it in any application or even modify the source in any way you see fit without restriction.
  • StructureMap is actually the oldest, original IoC tool for .Net with the first production release coming in June of 2004
  • I’m no longer the only person maintaining StructureMap
  • The source code is accessible here via Subversion in case you’re curious.  No credentials are required to access the source code.
  • Right now, StructureMap 2.5 will run on .Net 3.5 only.  I will most likely NOT be backporting the new version to 2.0 because of extensive usage of 3.5 features like Expressions
  • I swear that StructureMap 2.5 will run in medium trust on .Net 3.5 – but please post any problems that you do find with medium trust.
  • A 2.5.1 release is planned for the first week of December with bug fixes, a few new little features, Mono support, and a Silverlight-ready version (it’ll be a subset of the main library).

 

The Simplest Possible Usage of StructureMap

Your interaction with StructureMap is going to mostly consist of two activities:

  1. Asking StructureMap for an instance of a service or dependency (the easy part)
  2. Registering “what” and “how” StructureMap should build or find those requested services (the tedious part, but it’s gotten much better over the years)

In our system we use a service called “IValidator” to exercise validation rules on our domain model objects (I talked about the approach here).  By default, we want any consumer of the IValidator interface to use the concrete class named Validator.  Since we use StructureMap for resolving dependencies and services, we need to first tell StructureMap to use Validator anytime somebody asks for an IValidator.  You configure StructureMap by initializing the container with this code below:

    public static class ContainerBootstrapper

    {

        public static void BootstrapStructureMap()

        {

            // Initialize the static ObjectFactory container

            ObjectFactory.Initialize(x =>

            {

                x.ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

            });

        }

    }

Now that that code is called somewhere in the application initialization, we can get an IValidator object from StructureMap like in this sample code by calling ObjectFactory.GetInstance<IValidator>():

    public class ClassThatGetsAnIValidator

    {

        public void SaveObject(object objectToSave)

        {

            // Go get the proper IValidator from StructureMap

            IValidator validator = ObjectFactory.GetInstance<IValidator>();

 

            var notification = validator.Validate(objectToSave);

            if (notification.IsValid())

            {

                // save the object

            }

        }

    }

That’s it, your first usage of StructureMap.  No messy Xml configuration, no attributes scattered through your code, just a couple lines of bootstrapping code.   Of course, if that’s all StructureMap did, it wouldn’t be worth your time to download it.  Let’s look at a bit more advanced example.

 

Primitive Arguments

I actually like to use StructureMap as a generic configuration tool (which was actually its original purpose).  Let’s say you’re moving to the data access code.  You come up with some sort of Repository pattern class like this:

    public interface IRepository

    {

        void Save(object target);

    }

 

    public class Repository : IRepository

    {

        public Repository(string connectionString)

        {

            // set up the persistence infrastructure using the connectionString

            // from the constructor argument

        }

 

        public void Save(object target)

        {

            // save the object

        }

    }

The Repository class needs to be supplied with the “connectionString” in its constructor.  No problem, just set up the value of the constructor argument in the bootstrapping:

            ObjectFactory.Initialize(x =>

            {

                x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                    .WithCtorArg(“connectionString”).EqualTo(“a connection string”);

 

                // Or, since it’s smelly to embed a connection string directly into code,

                // we could pull the connection string from the AppSettings

                x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                    .WithCtorArg(“connectionString”).EqualToAppSetting(“CONNECTION-STRING”);

            });

With the bootstrapping out of the way, when we ask StructureMap for an IRepository in this code:

            var repository = ObjectFactory.GetInstance<IRepository>();

StructureMap will look up the “CONNECTION-STRING” value in the AppSettings portion of the App.config file, and use that string value to invoke the constructor function of the Repository class, then hand back that new Repository object.  Woo hoo.  We can build an object that doesn’t depend on anything, and we can build an object that needs some strings in its constructor function.  How about objects that need other non-primitive objects?

 

Auto wiring

In the code samples above, I used StructureMap as a Service Locator in the ClassThatGetsAnIValidator.SaveObject() method.  Typically, you’ll try to minimize the number of service locator usages in your system to a bare minimum (I found 8 in my current system, but I think I’ll find a way to prune half of those later).  Most of the value of an IoC tool is in automatically doing Dependency Injection.  I’m working with the new MVC framework at the moment, so it’s a handy sample.  Let’s say that we have a Controller class for a typical CRUD screen.  That Controller class will generally need to interact with both validation services and the data access functionality of the Repository.  Here’s a representative Controller class:

    public class SomeScreenController : IController

    {

        private readonly IRepository _repository;

        private readonly IValidator _validator;

 

        // SomeScreenController depends on both IRepository and IValidator

        public SomeScreenController(IRepository repository, IValidator validator)

        {

            _repository = repository;

            _validator = validator;

        }

 

    }

So let’s get StructureMap set up for this SomeScreenController class:

            ObjectFactory.Initialize(x =>

            {

                // Set up the IValidator

                x.ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

 

                // Set up the IRepository

                x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                    .WithCtorArg(“connectionString”).EqualToAppSetting(“CONNECTION-STRING”);

            });

You’ll notice that we didn’t make any explicit configuration for the SomeScreenController class, but yet we could now call:

           var controller = ObjectFactory.GetInstance<SomeScreenController>();

and StructureMap will happily create a new instance of the SomeScreenController class by invoking its constructor and passing in a new Validator object and a new Repository object created with the connection string from the App.config file.  We didn’t need to tell StructureMap how to construct SomeScreenController because:

  • StructureMap can look at the constructor function of SomeScreenController and see that it depends on IValidator and IRepository
  • StructureMap “knows” about the default way to create and return an IValidator and an IRepository

This feature is known as “auto wiring,” and all the mainstream IoC containers support this to some extent or another. 

 

 

What to do when things go wrong?

StructureMap, and any other IoC tool for that matter, is configuration intensive – which means that their will be problems in that configuration.  We’re all moving to more convention based type registration – which means that more stuff is happening off stage and out of your sight, making debugging the configuration even trickier.  Not to worry (too much), StructureMap has some diagnostic abilities to help you solve configuration problems.  The quickest tool is to ask a Container object or ObjectFactory (which is just a static wrapper around a Container) “what do you have?” with the Container.WhatDoIHave() method like this below:

            var container = new Container(x =>

            {

                x.ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

 

                x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                    .WithCtorArg(“connectionString”).EqualToAppSetting(“CONNECTION-STRING”);

            });

 

 

            Debug.WriteLine(container.WhatDoIHave());

Which would spit out this text into your output window:

===========================================================================================================
Configuration Sources:

0)   Registry:  StructureMap.ConfigurationExpression,StructureMap


===============================================================================================================================================================================================================================================================================================================================
PluginType                                                                                                                Name                                                                                                 Description                                                                                     
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ShadeTree.Validation.IValidator, ShadeTree, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null                         ShadeTree.Validation.Validator, ShadeTree, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null     ShadeTree.Validation.Validator, ShadeTree, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null
Built by:  StructureMap.Pipeline.BuildPolicy

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
StructureMapSample.IRepository, DovetailCRM.IntegrationTesting, Version=0.9.0.0, Culture=neutral, PublicKeyToken=null     27fdf13e-8adc-4f8f-9f53-cf7b35ada80c                                                                 Smart Instance for StructureMapSample.Repository                                                
Built by:  StructureMap.Pipeline.BuildPolicy

===============================================================================================================================================================================================================================================================================================================================

which is admittedly, not the prettiest looking thing in the world.

You can also “assert” that the configuration for a Container or ObjectFactory is complete by calling the Container.AssertConfigurationIsValid() method like this sample below:

            var container = new Container(x =>

            {

                x.ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

 

                x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                    .WithCtorArg(“connectionString”).EqualToAppSetting(“CONNECTION-STRING”);

            });

 

 

            container.AssertConfigurationIsValid();

This method will analyze every thing in the Container configuration and:

  1. Look for any missing constructor or mandatory setter arguments
  2. Look for any unknown dependency types
  3. Look for any errors in the Xml configuration (if you’re using Xml configuration)
  4. Try to build each and every type and named instance in the configuration – i.e. this is a complete, but relatively expensive operation
  5. Run any environment tests configured with the [ValidationMethod] attribute (a feature that is unique to StructureMap as far as I know)

The previous sample is a valid configuration, but let’s look at an invalid configuration.  Let’s omit the configuration of the “connectionString” constructor argument for the Repository class and try AssertConfigurationIsValid():

        [Test]

        public void lets_see_if_the_container_is_valid()

        {

            var container = new Container(x =>

            {

                x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>();

                    //.WithCtorArg(“connectionString”).EqualToAppSetting(“CONNECTION-STRING”);

            });

 

 

            container.AssertConfigurationIsValid();

        }

When I run the unit test above, this is part of the output:

 

Build Error on Instance '73b7f21b-bbfd-462c-854d-5b2a2f98ba50' (Smart Instance for StructureMapSample.Repository)
    for PluginType StructureMapSample.IRepository, DovetailCRM.IntegrationTesting, Version=0.9.0.0, Culture=neutral, PublicKeyToken=null

StructureMap.StructureMapException: StructureMap Exception Code:  205
Missing requested Instance property "connectionString" for InstanceKey "73b7f21b-bbfd-462c-854d-5b2a2f98ba50"

 

which again, isn’t the prettiest thing in the world, but it does tell me that the “connectionString” argument is missing for the Repository class.  After seeing this output, I think that this output and error wording will get improved in an upcoming release.

 

 

Why are you still rolling your own IoC tool?

Something that bothers me pretty is when I see bloggers frequently say that “StructureMap/Windsor/Ninject/Unity/Spring.Net/Autofac” is way too heavy for my project, so I just rolled my own.  Why?  Why would you do that?  Bootstrapping StructureMap for the very simplest cases, i.e. the only cases you can handle with the “roll your own IoC container in 30 lines of code solution,” takes 1 line of code for the call to ObjectFactory.Initialize() plus another line of code for each individual type.  

 

Related Links:

By no possible means was this a complete guide to using StructureMap or IoC tools in general.  Try these other links for more on StructureMap:

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.
  • David Kemp

    Thank you for WhatDoIHave().
    Instantly knowing I typed the wrong thing is is brilliant.

  • Jesper

    I am also getting Security Exception on medium trust. Hope there will be a solution soon.

  • http://jonerickson.me/ Jon Erickson

    I am getting the same error that @Tal is getting while running StructureMap under a medium trust hosting provider (GoDaddy). Still can’t find a fix or workaround.

  • http://www.talgiladi.net Tal

    It seems there is a problem running StructureMap on some shared hosting, I get a security exception “[SecurityException: That assembly does not allow partially trusted callers.]

    Any suggestions…?

  • http://www.bytecyclist.com Kyle LeNeau

    “I swear that StructureMap 2.5 will run in medium trust on .Net 3.5 – but please post any problems that you do find with medium trust.”

    I am attempting just this. I have tried setting the trust level in my web.config to medium in order to simulate my hosting provider. When the application starts up I receive a policy exception. (System.Security.SecurityException: That assembly does not allow partially trusted callers.) Any help will be greatly appreciated, I have searched the web and haven’t found much.

  • http://www.eknacks.com/SingleListView.aspx?li=121 eKnacks

    You’ve been knacked. Keep up the good work.

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

    @defeated,

    I will immediately start feeling guilty about not updating the Xml documentation and get back to writing soon.

    Yes, I will.

  • http://teamcianci.com/ Ed C.

    I know XML has gone out of fashion lately, but would it be possible to get updated documentation for XML-based configuration in StructureMap 2.5?

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

    @Brian Johnston,

    “I’m also finding testing with DI to be a PIA in general”

    One word: AutoMocker
    Ok, more words: AutoMocker + your own “InteractionContext” that acts as a base class for interaction style unit tests.

    “by using property injectors and lazy initialization ”

    To each his own, but I absolutely detest that idiom. I found it to be extremely problematic in the past. I still think Constructor Injection is much cleaner and more intention revealing.

    To expand:

    This code is useless without StructureMap configuration. Even worse, it’s not obvious from the outside of MyClass that it is dependent on SM configuration:

    public class MyClass
    {
    public void DoSomething()
    {
    var service = ObjectFactory.GetInstance();
    // use IService to do something

    }
    }

    This class can be used, reused, and tested, independently of the SM container:

    public class MyClass
    {
    public MyClass(IService service)
    {
    _service = service;

    }

    public void DoSomething()
    {
    // do stuff with _service field
    }

    }

    Remember, the container can do –> ObjectFactory.GetInstance() and set up the IService, then poke it into MyClass’s constructor with auto wiring, and it goes N-Deep.

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

    @Brian (not Johnston),

    I don’t deal with object cleanup at all, truth be told. SM by default, treats services as transients and does not hold on to anything. The only thing that is a concern are singleton “lifecycle” objects, but it’s assumed that you hang on to those long term. That is something I’m addressing in my next little release over the weekend.

  • Brian Johnston

    [Sorry if double post - site timed out]

    @Jeremy:

    In a previous comment to Dan you wrote: ‘Using service location creates direct coupling to the container and the container configuration. Dependency Injection does not. I’m personally not all that worked up about needing to swap out IoC containers, but having code dependent upon IoC configuration is a major pain in the ass in testing, and it will cut down on possible reuse.’

    Can you expand on that whole paragraph? A ‘bootstrapper’ class as you have in the Channel 9 demo is ‘coupling’ – and l think maybe that’s what you meant by ‘fine with’ – but I’m also finding testing with DI to be a PIA in general – though I’ve alleviated a lot of this by using property injectors and lazy initialization and in my tests use private accessors to set the backing field to my stub so DI doesn’t get used and that’s worked wonderfully. I get 100% coverage use stubs/mocks and still get DI in production (and then I have a small # of integration tests to ensure DI is being used for sanity purposes).

  • Brian

    How does SM handle clean up? In other words, one of my big disappoints with Castle Windsor was that for static objects, it was great, for items that were disposable, or even instance, it leaked memory all over the place because of maintaining references. Are you familiar with the problem I’m talking about? Has SM conquered this problem?

  • Oliver Klemencic

    As far as I know no IoC tool out there works without Reflection.Emit or similar technology. As we doing heavily development on .NET Compact Framework performance we build our our “IoC container”.

    At the beginning It only supported constructor injection but as we needed more features we just implemented them in 2-3 hours.

    Why do use anythings else?

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

    Dan,

    Using service location creates direct coupling to the container and the container configuration. Dependency Injection does not. I’m personally not all that worked up about needing to swap out IoC containers, but having code dependent upon IoC configuration is a major pain in the ass in testing, and it will cut down on possible reuse.

    “As of now I’ve only heard that constructor injection helps some developers understand their dependencies better.”

    Ditto from me on that one.

    Can’t you just inject the dependencies in? Or do you need to find the other object by name?

  • Dan Lash

    “In the code samples above, I used StructureMap as a Service Locator in the ClassThatGetsAnIValidator.SaveObject() method. Typically, you’ll try to minimize the number of service locator usages in your system to a bare minimum (I found 8 in my current system, but I think I’ll find a way to prune half of those later). ”

    I am wondering if you have any blog posts or resources on why you choose to shy away from the service locator pattern. We’re migrating our projects to use IoC moving forward, so I want to understand the pros and cons. As of now I’ve only heard that constructor injection helps some developers understand their dependencies better.

    Going beyond that, I have an example in a test project I’m working on that has a class that essentially sends messages to another — without a service locator, how would you use IoC to get instances of the message classes?

  • http://blog.phatboyg.com/ Chris Patterson

    Excellent introduction Jeremy, glad to have read it.

    @Andy,

    The problem with rolling your own is that eventually somebody other than you is going to have to maintain that code. Or somebody on the team is going to need that “one more feature” and implement it in a way that confuses the RYO solution. Eventually you have a big-ball-of-mud and that could have been avoided by using an off-the-shelf tool with documentation.

    And shouldn’t you developers be doing what is valuable: completing features for the customer. As Ayende said several times, if you are building infrastructure code for something that has already been done many times, you’re stealing from them.

    let your developers focus on the core domain of your application and leave the infrastructure to geeks like Jeremy that enjoy it. :)

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

    @Stephen,

    Fine enough, but remember that coding aesthetic does vary from person to person. Plenty of people do like the SM API. I’ve actually backed off of the method chaining in SM 2.5 quite a bit in favor of nested closures with lambdas. I think the Lambda issue is mostly the “newness” rather than an overarching problem.

  • Stephen

    As great as structure map is, I feel the code is ironically harder to read because of all the lambda and fluent infaces going on.. the irony being that fluent interfaces especially are there to make things more ‘ingrish’..

    I just think theres a lot of hype about fluent interfaces, but many of them actually are so different looking to ‘code’ I feel like I have to transition myself to read them.. probably even more so than I have to transition myself between say.. vb and c#.

    2c

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

    @Andy,

    “You need a IOC but your work place won’t allow code that uses an OSS license (crazy yes but it happens).”

    Unity. I don’t think it measures up to the others, but it does the simple cases just fine and it’s from MS.

    “You only need a basic IOC and RYO will meet your requirements (you could always refactor it out to another IOC if the design is right).”

    Again, how is that possibly more efficient than simply downloading an existing tool?

  • http://weblogs.asp.net/astopford Andy Stopford

    >>Why are you still rolling your own IoC tool?

    Lots of reasons why you might.

    You need a IOC but your work place won’t allow code that uses an OSS license (crazy yes but it happens).

    You only need a basic IOC and RYO will meet your requirements (you could always refactor it out to another IOC if the design is right).

    Andy