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

Introduction to using StructureMap for Dependency Injection

StructureMap is an open source tool I’ve written for Dependency Injection support in .Net.  This past week I’ve had a couple requests for a gentle introduction to StructureMap, so here’s my first attempt.  Typically I use StructureMap in a handful of ways:

 

  1. Configuration and creation of services (little “s”) that my code depends upon.  By service here I don’t necessarily mean SOA and web services, but web service proxy classes are an automatic candidate for StructureMap configuration.  I’m referring to subsystems of your application like logging modules, persistence, gateways to other systems, or really anything that you don’t want your code to be tightly coupled to.
  2. Object composition.  Code reuse and unit testing is easier when you favor composition over inheritance relationships, but composition implies that you need to some mechanical coding work just to put the object graph together.  This is where StructureMap comes into play.
  3. Plugin support.  Occasionally there is a real need for pluggable, extensible application frameworks.

 

 

A Contrived Example

 

Let’s say you’re an integration developer in a shop with a crazily mixed bag of applications floating around a big central database.  You want to write a pluggable infrastructure for batch scheduling little integration tasks.  You may need to pull data by a sql query, a stored procedure, or by opening a file – then do something with the data.  All you really know is that the possible sources of the data and the actions on the data will change over time.  You might decide to create a pluggable framework using StructureMap to handle the configuration (Okay, in reality you would probably buy something off of the shelf or utilize DTS out of the box, but I needed an example).

 

First off, let’s ignore the configuration schema and concentrate on defining a set of interfaces and roles for our “Trigger” framework.  The main interface will be this:

 

      public interface ITrigger

      {

            // Do whatever it is that you do

            void Execute();

 

            // Tell me when you want to run next

            DateTime NextExecutionTime();

      }

 

Configuring the most basic trigger class will define the mechanism to retrieve the data, an action to perform on the data, and a strategy for determining the next run time (next Monday, the top of the next hour, the last day of the month, etc.).  That adds the following code:

 

      [Pluggable("Basic")] // Tell StructureMap that it "builds" this class and that it's alias is "Basic"

      public class Trigger : ITrigger

      {

            private readonly IScheduler _scheduler;

            private readonly IDataSource _source;

            private readonly IAction _action;

 

            public Trigger(IScheduler scheduler, IDataSource source, IAction action)

            {

                  _scheduler = scheduler;

                  _source = source;

                  _action = action;

            }

 

            public void Execute()

            {

                  DataTable table = _source.FetchTable();

                  _action.Process(table);

            }

 

            public DateTime NextExecutionTime()

            {

                  return _scheduler.GetNextRunTime(DateTime.Now);

            }

      }

 

      public interface IDataSource

      {

            DataTable FetchTable();

      }

 

      public interface IAction

      {

            void Process(DataTable table);

      }

 

      public interface IScheduler

      {

            DateTime GetNextRunTime(DateTime currentTime);

      }

 

The first Trigger that we’re going to need to build is going to daily run a SQL query against the central database, and then email the results to an unlucky support person for resolution.  First we create the little classes for the scheduling, data source, and the action.

 

      [Pluggable("SQL")]

      public class SqlDataSource : IDataSource

      {

            private readonly string _sql;

            private readonly IDatabase _database;

 

            public SqlDataSource(IDatabase database, string sql)

            {

                  _sql = sql;

                  _database = database;

            }

 

            public DataTable FetchTable()

            {

                  return _database.FetchDataTable(_sql);

            }

      }

 

      [Pluggable("Email")]

      public class EmailAction : IAction

      {

            public EmailAction(string to, string body){…}

            public void Process(DataTable table){…}

      }

 

      [Pluggable("Daily")]

      public class DailyScheduler : IScheduler

      {

            public DailyScheduler(){}

            public DateTime GetNextRunTime(DateTime currentTime){…}

      }

 

SqlDataSource itself depends upon the IDatabase interface that provides access to an underlying database and handles the raw ADO.Net manipulation.  Let’s say that the central database is a Sql Server database (but I’m starting to miss good old reliable Oracle).  That adds the following to the code:

 

      public interface IDatabase

      {

            DataTable FetchDataTable(string sql);

            void SetStoredProcedureName(string storedProcedureName);

            void SetParameter(string parameterName, object parameterValue);

            DataTable FetchDataTableFromStoredProcedure();

      }

 

      public class SqlDatabase : IDatabase {…}

 

Okay, now we can finally make our StructureMap configuration to create the object graph for our first Trigger.  The first thing we need to do is create a file named “StructureMap.config” that will be copied to the application directory.  At a minimum, we need to define four things for StructureMap:

 

  1. <Assembly> - The .Net assemblies to scan for possible interfaces and classes to be built by StructureMap
  2. <PluginFamily> - The .Net types that can be requested from StructureMap.  In our case this would be the ITrigger, IDataSource, IAction, and IScheduler interfaces.  It can also be abstract or concrete classes as well.
  3. <Plugin> - The concrete .Net types that will implement the interfaces of the PluginFamily types.
  4. <Instance> - The actual object graph configurations.  Notice that we didn’t do anything special in our classes to enable StructureMap (except the [Pluggable] attributes).  All you need to do to enable your class to be configured by StructureMap is to take in all dependencies and properties in a constructor function.  StructureMap also supports “Setter Injection,” but that’s really just meant for Types that aren’t under your control.

 

Jumping into the StructureMap.config file we’ll first configure the default IDatabase instance to point to the central Sql Server database.

 

<?xml version="1.0" encoding="utf-8" ?>

<StructureMap>

      <!-- Tell StructureMap to scan the StructureMapSample.dll assembly for possible PluginFamily's and Plugin's -->

      <Assembly Name="StructureMapSample" />

     

      <!-- Define a PluginFamily for IDatabase, making the default instance "CentralDatabase" -->

      <PluginFamily Assembly="StructureMapSample" Type="StructureMapSample.IDatabase" DefaultKey="CentralDatabase">

            <!-- Tell StructureMap that the SqlDatabase class is a plugin to IDatabase called "MicrosoftSqlServer" -->

            <Plugin Assembly="StructureMapSample" Type="StructureMapSample.SqlDatabase" ConcreteKey="MicrosoftSqlServer"/>

           

            <!-- Configure the "CentralDatabase" instance of IDatabase.  The <Property> nodes define the arguments to the constructor

            functions -->

            <Instance Key="CentralDatabase" Type="MicrosoftSqlServer">

                  <Property Name="connectionString" Value="connection string to somewhere..."/>

            </Instance>

      </PluginFamily>

</StructureMap>

 

With this configuration we could at anytime in our code type IDatabase database = (IDatabase) ObjectFactory.GetInstance(typeof(IDatabase)); to get a configured instance of the SqlDatabase class with the connection string set.  If the database changed to Oracle or DB2 later, only the configuration to create a different concrete IDatabase class would be changed (yeah right).  In this case I defined the Plugin explicitly in the XML configuration.  The [Pluggable(“My Plugin Alias”)] attribute is an equivalent mechanism to using the <Plugin> node.  I prefer the attributes wherever possible, but some people feel differently. 

 

Moving on to the first Trigger instance, we would add a <PluginFamily> node for ITrigger and an <Instance> node for the object graph for the first Trigger.

 

      <PluginFamily Assembly="StructureMapSample" Type="StructureMapSample.ITrigger">

            <!-- Create a BasicTrigger object, and give it a DailyScheduler, -->

            <!-- Uses the public Trigger(IScheduler scheduler, IDataSource source, IAction action) constructor function -->

            <Instance Type="Basic" Key="MyFirstTrigger">

           

                  <!-- DailyScheduler -->

                  <Property Name="scheduler" Type="Daily" />

                 

                  <!-- SqlDataSource(IDatabase database, string sql) -->

                  <!-- By leaving off an explicit definition for "database" StructureMap will use the default

                       "CentralDatabase" instance -->

                  <Property Name="source" Type="SQL">

                        <Property Name="sql" Value="select * from errorlog"/>

                  </Property>

                 

                  <!-- public EmailAction(string to, string body) -->

                  <Property Name="action" Type="Email">

                        <Property Name="to" Value="poorfool@helpdesk.company.com"/>

                        <Property Name="body" Value="Fix these now!" />

                  </Property>

            </Instance>

      </PluginFamily>

 

The Trigger framework can now create this instance by calling into StructureMap as something like this:

 

            public void RunTriggers()

            {

                  string[] triggersToRun = this.findTriggersToRun();

 

                  foreach (string triggerName in triggersToRun)

                  {

                        // Ask StructureMap to build the object instance

                        ITrigger trigger =

                              (ITrigger) ObjectFactory.GetNamedInstance(typeof(ITrigger), triggerName);

 

                        trigger.Execute();

                        DateTime nextTime = trigger.NextExecutionTime();

 

                        this.rescheduleTrigger(triggerName, nextTime);

                  }

            }

 

Additional trigger’s could be created by simply configuring the object graphs into the StructureMap.config file as a new <Instance> node.  The big advantage in this case is that StructureMap can quite happily accommodate any new classes that you create later to implement the ITrigger/IDataSource/IAction interfaces.  You could even “plugin” all new assemblies to be used by your application without recompilation.  That’s potentially a huge win for my company because of the sheer number of per client customizations that we have to do.

 

There is far more information and an actual schema document at http://structuremap.sourceforge.net.  I threw this together in a hurry, so please let me know if this is useful or if something else is necessary to make the tool more clear.  Sometime in the near-ish future I’ll post much more on some of the new capabilities for configuration management and environment testing that we’re building into StructureMap for complex build and staging scenarios.



Comments

Jeremy D. Miller -- The Shade Tree Developer said:

This is a follow up to my post on the Model View Presenter pattern with ASP.Net to address or clarify...
# February 16, 2006 1:18 AM

Jeremy D. Miller -- The Shade Tree Developer said:

Author: &lt;a href=&quot;blogs/jeremy.miller&quot;&gt;Jeremy D. Miller&lt;/a&gt;&lt;br /&gt;Carlton commented that the Presenter class looks a lot like the Gang of Four &quot;Mediator&quot; pattern. He's absolutely right. Something to keep in mind when learning to apply design patterns is that a class or group of classes can easily be an instance of more than one pattern. In this case &quot;Presenter&quot; or &quot;Controller&quot; is just a more specific name for a class within a larger structural pattern.
# February 16, 2006 9:22 AM

Jeremy D. Miller -- The Shade Tree Developer said:

This past Saturday was the Austin Code Camp.&amp;nbsp; I had a great time and the general consensus was that...
# March 6, 2006 8:32 AM

Yi said:

It's really nice framework! I am going to use it in my project.
# July 6, 2006 2:44 PM

Yi said:

A quick question about ObjectFactory.GetInstance(typeof(IDatabase));.

Does the OjbectFactory caches the instance or it reads the configuration file and search the assembly every time GetInstance is called?
# July 6, 2006 3:07 PM

Jeremy D. Miller said:

Yi,

Not quite either.  Unless you explicitly specify the Scope property ObjectFactory.GetInstance() will return a new instance per request.

StructureMap largely caches the configuration.  Scanning assemblies and parsing the StructureMap.config file only happens once on the first call to ObjectFactory (unless you force the issue with ObjectFactory.ResetDefaults()).

Jeremy
# July 6, 2006 3:19 PM

Yi said:

Thanks Jeremy! So by default, ObjectFactory creates new instance for each request. However, it reads config file and scans assemblies only once. I also find what you just said in the documentation:
"New in version 1.0 is the ability to quickly define different creation modes.  This functionality can be configured with the new optional "Scope" property on the [PluginFamily] attribute or the "Scope" attribute on the <PluginFamily> node."

I just put in an Authentication Plugin for my project. I was kind of curious if StructureMap will increase the memory usage. I barely notice the difference. Very nice work! :)
# July 6, 2006 5:04 PM

Jeremy D. Miller -- The Shade Tree Developer said:

The slide deck and sample code from my StructureMap talk last night is available from the ADNUG downloads...
# July 11, 2006 10:52 AM

Yi said:

Hello Jeremy,

I wonder where I can find XSD file for the StructureMap.

Thanks!

Yi
# July 27, 2006 2:57 PM

Jeremy D. Miller said:

Yi,

I've never made one.  Some of the nodes and attributes are dynamic, so it's not really going to be possible anyway.

Sorry,

Jeremy
# July 27, 2006 4:13 PM

Yi said:

Interesting. Can you give me an example about these "dynamic nodes and attributes"? Thank you in advance!

Yi
# July 27, 2006 4:36 PM

Daniel Essin said:

I'm very impressed with the work that you've done on StructureMap. I know that I need something like this that allows a degree of abstraction, but I've always been a bit challenged by higher math so I'm having a hard time absorbing all the fine points. I've got a couple of questions that you perhaps could help me with.

First off, I want to mention that in order to run the StructureMap Explorer under .net 2.0 you need to as a [STAThread] attribute to the main or an exception is thrown when trying to create the browser component.

I'm sure that you're familiar with sharpDevelop. I am trying to do something like that - create a platform for my apps that will provide all of the basic services such as encryption, authentication, logging, etc. and into which all of the application-specific forms and functions will "plug in"

I've studied the possibilty of simply using the sharpDevelop shell and replacing all of the content, using Spring.NET or using StructureMap. I've also looked as SAF (Simple application framework) by chen.

I have stepped through the code in sharpDevelop dozens of times and I understand what it is doing pretty well but their external xl config files are so complex that every time I try to alter one the whole thing breaks. My opinion of that platform is that without a gui utility to examine your assemblies and write the .addin files, it will probably never work for me.

I like the feature in Spring.NET of being able to embed the config for each assembly in a resurce and extract it during the load. This reduces the possibility that the config file will get lost, corrupted or damaged by a user trying to alter its behavior. For the same reason I like the idea of being able to accomplish the configuration of StructureMap by applying attributes to the classes.

Am I correct in my understanding that what you have done in the StructureMap  Explorer app is to have accomplished the entire configuation with attributes and that is why there is no .config file for the app?

Becaus I am abstractionally challenged, I would appreciate it if you could give me some guidance about how to best have assemblies contribute items to the menubar,child forms that are invoked or affected by selecting different tree nodes (like in your explorer, and how I can osilate all of the commands that are executed in one place so the can be invoked form either a menu, form event or a use typing a command at a prompt?

Thanks,

Dan Essin (essin@ieee.org)

# September 17, 2006 7:50 PM

Jeremy D. Miller said:

Dan,

The STAThread is a known issue, and if you'll give me a little while I'll get an example up showing how to use StructureMap sans config file to do exactly what you're trying to do.

Jeremy

# September 17, 2006 9:16 PM

Daniel Essin said:

That would be great. Thanks.

# September 18, 2006 5:12 PM

Yi said:

Hello Jeremy,

I just dropped an email to your yahoo mail. I encountered some issue when using StructureMap with Windows Service. The .NET runtime complains that "System.Runtime.Serialization.SerializationException: Unable to find assembly 'StructureMap, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'." I double-checked that the structuremap.dll is in the working dir.

I wonder if you used StructureMap with Windows Service. I hope you can shed me some light on this one.

Thanks!!!

Yi

# December 7, 2006 2:26 PM

Suresh said:

Hai Jeremy,

I have a doubt in my application for using StructureMap.

Can you tel me actually usage is like a Factory pattern.

Is it right??

In my application i got the instance of a Concrete class, it has more than 10 subclasses with the usage of n number of XmlSchema ( object). But the XmlSchema are use used in the different n number of Concrete classes..

if i want to do any changes in one schema in one Concrete class that also depends on the n-1th concrete class ( Object dependency exists here.. ). can u tel me,  can i use Structure map container, is it helpful for me...

else can you tel me which pattern is optimal one..

i need help

my mail id is : vasuresh@jeevantechnologies.com

Thanks

Suresh

# January 3, 2007 3:16 AM

Jeremy D. Miller -- The Shade Tree Developer said:

It took long enough, and I&#39;ve had a pretty good stream of people asking for this, so here it is:

# April 2, 2007 10:28 AM

kasajian said:

I got my hands dirty and learned DI/IoC by studying the crystalproject.org API.  I found Simone Busoli's introduction to it on dotnetslackers.com to be one of the best introductions on DI, if not one of the best articles written in general.

So now understand it and am quite impressed with the cleanness of the crystal implementation.  My plan was to study the other DI packages out there and then do a comparison, but frankly, when I start to go down the path of learning ObjectBuilder and even StructureMap, I quickly lose interest because the introductions start out more complex and convoluted than what crystal offers.  I realize that I'm probably not being as fair to the other frameworks, but as many of us having relatively limited time, it seems as though there ought to be a better for people to decide between the different frameworks.  There out to be a comparison article that  does justice to the existing frameworks.

Another thing that's missing is that the DI introductions I've seen thus far focus on the programmatic use of the APIs, which some people prefer.  But I strongly believe that the configuration based method has a lot more value.  It would be good to have an introductory article to each of the DI frameworks for those shops that are planning on configuring the containers using external files and minimize the attributes and APIs in the code.

Thank you for listening. :)

# December 15, 2007 9:22 PM

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# January 25, 2008 4:22 AM

Ryan Lanciaux said:

Very Quick and Simple Dependency Injection with StructureMap

# February 27, 2008 12:22 AM

VusCode - Coding dreams since 1998! said:

On my quest to design for testability, I&#39;ve already covered: Part 1 - Separation of concerns (SOC

# March 3, 2008 4:59 AM

Scott Hanselman's Computer Zen said:

# March 14, 2008 1:15 AM

ASPInsiders said:

I'm trying to expand my mind around dependency injection in .NET (beyond the two frameworks I've personally

# March 14, 2008 2:18 AM

Itzik Kasovitch said:

Is it possible to add components manually to structure map's object factory? For example I want to create some object manually and the add it to structure map like it is done in WindsorContainer using AddComponent.

# June 1, 2008 7:02 AM

Jeremy D. Miller said:

@Itzik,

With 2.0, ObjectFactory.InjectStub<T>(T object);

With the 2.5 trunk, the above still works, but there are far more options.

ObjectFactory.Inject<T>(T object);

# June 1, 2008 10:21 AM

Itzik Kasovitch said:

I have checked out structuremap from sourceforge and tried to run the build script. Unfortunately, it failes. It seems that some files are missing. Should I make some settings to be able to run the build successfully. If so, where are the guidelines?

# June 2, 2008 10:55 AM

ms440 said:

Hi Jeremy,

I've used the StructureMap 1.0 in one of my prev project.

After watching the screencast that you and Rob Conery put together last week, I realized that I'd like to get back to StructureMap in my new project (not ASP.NET MVC) again. Two questions though:

First, during the screencast you've promised to put together some documentation for 2.5. What's the ETA for that? Would I be able to use it within my application project timeframe (I'll have to make a decision about the use of StructureMap before the end of June :(.

Second, I checked out the code for 2.5 and couldn't compile it (as with Itzik Kasovitch case). Could you please take a look into the problem he's discovered?

Third and most important! Thanks a lot for your excellent and extremely useful work on patterns in general (congrats on your MSDN article - pure pleasure to read) and StructureMap in particular.

# June 10, 2008 10:26 PM

Cliff said:

Is it possible to use StructureMap to map types across projects without having a reference?  For example, if you have three projects: web (references model), model, and data (references model) can you in the web project set up a mapping from an interface in the Model project to a concrete type in the Data project, without having a project reference to data from web?

# June 15, 2008 12:07 AM

Jeremy D. Miller said:

@Cliff,

Yes, but watch your build procedures.  You'll have to pull that off in the Xml, or create a completely new assembly that references all three of the other assemblies just to hold the STructureMap configuration.  One way or another, StructureMap has to be able to load any assembly through the normal mechanisms.  You'll have to copy around the assemblies yourself instead of depending upon VS to do it for you.

# June 18, 2008 10:59 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!

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