CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

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:



Comments

A Gentle Quickstart for StructureMap 2.5 | bestwebhostingservices.com said:

Pingback from  A Gentle Quickstart for StructureMap 2.5 | bestwebhostingservices.com

# December 1, 2008 3:39 AM

Reflective Perspective - Chris Alcock » The Morning Brew #234 said:

Pingback from  Reflective Perspective - Chris Alcock  &raquo; The Morning Brew #234

# December 1, 2008 5:50 AM

Andy Stopford said:

>>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

# December 1, 2008 7:43 AM

Jeremy D. Miller said:

@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?

# December 1, 2008 8:07 AM

Dew Drop - December 1, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - December 1, 2008 | Alvin Ashcraft's Morning Dew

# December 1, 2008 9:30 AM

Stephen said:

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

# December 1, 2008 9:38 AM

Jeremy D. Miller said:

@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.

# December 1, 2008 9:42 AM

Chris Patterson said:

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. :)

# December 1, 2008 9:42 AM

Dan Lash said:

"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?

# December 1, 2008 1:45 PM

Jeremy D. Miller said:

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?

# December 1, 2008 3:19 PM

Oliver Klemencic said:

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?

# December 1, 2008 4:40 PM

where did the name google come from | Digg hot tags said:

Pingback from  where did the name google come from | Digg hot tags

# December 1, 2008 10:28 PM

GR Shared Link - A Gentle Quickstart for StructureMap 2.5 - FreePress Blog said:

Pingback from  GR Shared Link - A Gentle Quickstart for StructureMap 2.5 - FreePress Blog

# December 2, 2008 2:13 AM

2008 December 02 - Links for today « My (almost) Daily Links said:

Pingback from  2008 December 02 - Links for today &laquo; My (almost) Daily Links

# December 2, 2008 5:11 AM

Brian said:

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?

# December 2, 2008 8:41 PM

Brian Johnston said:

[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).

# December 2, 2008 9:04 PM

Jeremy D. Miller said:

@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.

# December 2, 2008 9:13 PM

Jeremy D. Miller said:

@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<IService>();

      // 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<MyClass>() and set up the IService, then poke it into MyClass's constructor with auto wiring, and it goes N-Deep.

# December 2, 2008 9:20 PM

defeated said:

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?

# December 4, 2008 8:28 PM

Jeremy D. Miller said:

@defeated,

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

Yes, I will.

# December 4, 2008 9:06 PM

eKnacks said:

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

# December 6, 2008 6:32 AM

Elegant Code » Learning about StructureMap said:

Pingback from  Elegant Code &raquo; Learning about StructureMap

# December 12, 2008 6:25 PM

Kyle LeNeau said:

"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.

# December 15, 2008 12:55 PM

Tal said:

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...?

# December 31, 2008 2:41 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

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 previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

Our Sponsors

Proudly Partnered With


This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP