Before you use an IoC tool, some concepts to know first

 
JEREMY’s NOTE:  I’m trying to rewrite the StructureMap documentation today, and I’m going to blog most of it out here as I finish it until Brendan tells me to stop polluting the main feed.  This article is intended to be an introduction to the concepts behind an IoC tool for folks with little or no previous exposure.  Feedback will be very much appreciated.
 
 
From my original release back in June 2004:  StructureMap is a Inversion of Control (IoC) slash Dependency Injection framework that can be used to improve the architectural qualities of an object oriented system by reducing the mechanical costs of good design techniques.  Using StructureMap does not in any way improve your architecture per se, it simply strives to make the mechanics of a good Object Oriented Design cheaper to implement.  Additionally, StructureMap allows you to efficiently exploit a well designed Object Oriented architecture to provide extensibility mechanisms, flexible deployment options, and self validating configuration and deployment.

Over the years a series of concepts and principles have been discovered and developed to describe well-structured Object Oriented systems.  To most effectively use StructureMap, or any other IoC tool for that matter, your system needs to be designed with these principles first:

To sum it all up, well designed Object Oriented systems are composed of many objects that work with each other to accomplish to goals of the system.  We want our systems to be decomposed into cohesive classes that perform a well defined responsibility within the system, rather than monolithic “God” classes that do too much.  A cohesive class will have to be dependent upon other classes to perform services outside of its own tightly defined responsibility.  In IoC speak, we call the collaborating objects dependencies

 

Dependencies

For example, in my current system we have a class called AddressEditController that governs the creation and editing of Address entities in our web based UI.  The AddressEditController needs to validate user input and persist or load data.  Those are two distinct responsibilities, so AddressEditController has dependencies on other objects for these services. 

    public class AddressEditController : Controller

    {

        // AddressEditController uses IValidator to validate user input

        // and IRepository to load and save Address information

        private readonly IValidator _validator;

        private IRepository _repository;

 

    }

So here’s some facts about AddressEditController:

  • AddressEditController depends on IValidator and IRepository 
  • AddressEditController cannot function unless it has both an IValidator and an IRepository
  • From the concepts section above, for best results, the AddressEditController should be loosely coupled to its dependencies by knowing as little about the inner workings of the real IValidator and IRepository
  • The real IRepository is a Gateway into NHibernate. The concrete Repository class cannot be used without its own dependency trail of external configuration, a Singleton to keep track of an expensive resource, and some NHibernate bootstrapping code. 

Just calling a new() constructor on its dependencies isn’t the best design for our AddressEditController.  Creating a concrete Validator class is very possible, but what if we want to selectively replace the implementation of IValidator later?  That’s only somewhat likely, but the dependency on Repository is a much larger concern.  I might have semantic decoupling between AddressEditController and Repository, but if AddressEditController calls new Repository() itself, AddressEditController will not be able to function without all that NHibernate bootstrapping.  I do not want a piece of my user interface to be tightly coupled to the existence of the persistence layer. 

In other scenarios, creating the dependencies may involve more than just calling new() on the dependencies (don’t believe me?  Go try to create an HttpContext object).

AddressEditController is responsible for the workflow around editing Address entities in the UI.  It shouldn’t be concerned with NHibernate configuration and whatnot.  One way to solve this problem is to move the responsibility for building its dependencies to somewhere external to AddressEditController

 

Inversion of Control and Dependency Injection

In many cases, I don’t want my classes to have to be aware of how their dependencies are created or located.  I don’t want controller classes to even care that they’re using an object that is created via Microsoft’s Provider infrastructure, or a Singleton, or needs configuration data.  My class should only know the public interfaces of its dependencies.  I can make that true by applying “Inversion of Control.”  Instead of doing:

        public AddressEditController()

        {

            _validator = new Validator();

            _repository = new Repository();

        }

where AddressEditController calls linearly through to the constructors on Validator and Repository, we can invert the control to make the creator of AddressEditController responsible for building the dependencies and “pushing” them into AddressEditController

    public class AddressEditController : Controller

    {

         private readonly IValidator _validator;

        private IRepository _repository;

 

        public AddressEditController(IValidator validator, IRepository repository)

        {

            _validator = validator;

            _repository = repository;

        }

    }

The code sample above uses a form of Inversion of Control called Dependency Injection to push in the dependencies via a constructor function.  Of course, at some point, something needs to know how to create the entire chain of dependencies and do all of that Dependency Injection.  StructureMap supports a pattern known as Service Locator:

            // Creates an AddressEditController with all of its dependencies

            AddressEditController controller = ObjectFactory.GetInstance<AddressEditController>();

ObjectFactory is a StructureMap class that serves as a well known place to go and find any service that you need.  When the AddressEditController is created and returned by ObjectFactory, it should be completely ready to go.  There’s another important concept to understand before you use StructureMap. 

 

Auto Wiring

Every “real” IoC container supports the concept of “Auto Wiring.”  Auto Wiring simply means that StructureMap can figure out dependency chains for you without a lot of explicit configuration.  When you ask for AddressEditController, there is more going on than just AddressEditController and its two dependencies.  The Repository class itself has its own dependencies.

        [DefaultConstructor]

        public Repository(ISessionSource source) : this(source.CreateSession())

        {

 

        }

In turn, the concrete version of ISessionSource above has its own dependencies:

        public SessionSource(IDictionary<string, string> properties, PersistenceModel model)

        {

            _configuration = new Configuration();

            _configuration.AddProperties(properties);

 

            model.Configure(_configuration);

 

            _sessionFactory = _configuration.BuildSessionFactory();

        }

which starts to get interesting because SessionSource needs some information like connection strings that have to come in from Xml configuration: 

<StructureMap MementoStyle=Attribute>

  <DefaultInstance

    PluginType=ShadeTree.DomainModel.ISessionSource,ShadeTree.DomainModel

    PluggedType=ShadeTree.DomainModel.SessionSource,ShadeTree.DomainModel>

    <properties>

      <Pair Key=connection.provider Value=NHibernate.Connection.DriverConnectionProvider />

      <Pair Key=connection.driver_class Value=NHibernate.Driver.SqlClientDriver />

      <Pair Key=dialect Value=NHibernate.Dialect.MsSql2000Dialect />

      <Pair Key=hibernate.dialect Value=NHibernate.Dialect.MsSql2000Dialect />

      <Pair Key=use_outer_join Value=true />

      <Pair Key=connection.connection_string Value=a connection string that I’m certainly not giving out to you! />

      <Pair Key=show_sql Value=true />

    </properties>

  </DefaultInstance>

</StructureMap>

Here’s some of the configuration for the other services that the entire EditAddressController needs:

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

            ForRequestedType<IRepository>().TheDefaultIsConcreteType<Repository>().CacheBy(InstanceScope.Hybrid);

            ForRequestedType<PersistenceModel>().TheDefaultIsConcreteType<DovetailPersistenceModel>();

At no point did I specify that EditAddressController needs an IRepository that needs an ISessionSource that needs 2-3 other things, but yet when I call:

            // Creates an AddressEditController with all of its dependencies

            AddressEditController controller = ObjectFactory.GetInstance<AddressEditController>();

StructureMap will construct EditAddressController that had a new instance of Repository that had a new instance of SessionSource that had an IDictionary<string, string> object and a new instance of DovetailPersistenceModel.  I don’t have to explicitly tell StructureMap to do that for me because it uses its “Auto Wiring” feature to examine the dependencies of each concrete class and act accordingly.  StructureMap does need to know what to do with each type of object it encounters.  When it tries to build the Repository class StructureMap sees the constructor argument for ISessionSource on Repository, and knows to build and inject a new SessionSource object (and so on as deep as you need to go).

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.
  • li.chen

    Hello,I Have a question, Sorry I’m English very rubbish, I paste up code.See Image, I setting “Sender Class” construction EmailLog, but run programe, resule log use FileLog! How I Modify the xml cofnig?

  • sachin ruhela

    Access File Repair
    access password recovery
    Access Password Recovery Software
    MS Access Password Recovery
    Access Password Recovery Tool
    Fix Excel
    download free key logger
    Chat Archive Recovery
    Database conversion software
    MS excel repair software
    Data Recovery Tool
    Web Hosting
    Free Data Wiper
    Digital camera photo recovery software
    Disk Recovery Software
    Data recovery software free download
    Database Converters
    Free Keylogger
    Excel File Recovery
    MS Access Password Recovery Tool
    Excel Recovery
    free keylogger software
    Floppy Recovery
    Repair Excel
    Excel Repair
    recover msn password
    Excel File Fix
    Floppy Disk Recovery
    Windows Data Recovery
    Keystroke Logger
    Hard drive data recovery
    Free Excel Recovery
    Windows Recovery Tools
    IE Password Recovery
    IPod Recovery
    Key logger
    Excel Recovery Tool
    download a free keylogger
    keyloggers free
    keylogger freeware
    Keylogger Spy Software
    keylogger software free
    keystroke capture
    Keylogger
    Recovery Password
    free keylogger downloads
    best keylogger free
    msn password recovery
    Outlook Express Password Recovery Software
    password finder
    Keylogger Software Download
    Password Recovery
    password recovery software
    password recovery software free
    pen drive data recovery software
    Pen Drive Recovery
    PowerPoint Repair Tool
    Chat Recovery Software
    Fix Excel File
    Restore Excel File
    Email Recovery
    cell phone sms recovery software
    recovery for excel
    Repair Excel Files
    repair excel files software
    Data Recovery Software
    sim card deleted sms recovery
    SIM Card Data Recovery
    Key logger software
    downloadable keylogger
    download keylogger freeware
    free invisible keylogger
    data recovery
    Download Free Keylogger
    keystroke recorder
    software keylogger
    remote key logger
    sim recovery
    Sim Card Recovery
    Backlinks Checker Tool
    remote keylogger free
    Spy Keylogger
    USB drive data recovery
    Free Backlink Finder Tool
    datarecovery
    Zip Repair Tool
    Data recovery software for NTFS
    Recovery Format Data
    Partition recovery software
    SEO
    Backlinks Checker
    Sim Card SMS Recovery
    Word file repair software
    data recovery services

    Is good for this post. Your blog is very interesting and great information, thanks

  • http://www.key-logger.ws/ keylogger

    Well thanks to
    information.

  • Developer

    Very good article, very useful.

  • Brian Johnston

    @JEREMY’s NOTE: I’m trying to rewrite the StructureMap documentation today, and I’m going to blog most of it out here as I finish it until Brendan tells me to stop polluting the main feed. This article is intended to be an introduction to the concepts behind an IoC tool for folks with little or no previous exposure. *Feedback will be very much appreciated.*

    Two things have always been top-most in my mind:

    1) A hello-world walk-through – and I mean ‘hello-world’ – as dumbed down as it can get with every step there (assume your reader/watcher is complete moron with no ability to figure anything out on there own).

    The reason being is people like myself, this is what make or breaks our interest. Naturally I’ll have some interest because I’ve read your stuff for a while, know your a smart guy, and conceptually understand what your doing with the framework and how it can build a better product, but that alone won’t sell me. When I get on the site and start looking at the API docs, I can only read those long pieces of documentation and all the ‘getting into the weeds’ code when I have a genuine interest in the technology. A hello world can actually do that for me.

    Taking your examples above…you lost me pretty quickly – first you hit me with a bunch of design principals, some okay for the context, some a little to technical for newbies (# Open Closed Principle, the Single Responsibility Principle, and the Liskov Substitution Principle and # Dependency Inversion Principle) – pretend your talking to management, keep the summary (and don’t be afraid to expand upon it!) and just add those links for ‘further reading’. Next you got straight into real world code. I don’t work where you work – so instead of focusing on how the framework can help me I’m sitting here wondering why you have a separate controller for just handling address because we use a controller that covers the entire customer (including addresses)…see what I’m saying? I’m getting lost in the weeds rather than focusing on the benefits of the framework. I want the real world code, but later, after I got the framework down.

    From a hello world I can generally determine (a) is it the right fit for me on the current project or possibly an upcoming one? (b) is it going to be hard to get other developers to use (c) is it creating more problems than its solving for my current project (d) am I’m going to spend 80% of my time implementing 20% of the project in order to use this framework (e) (if applicable) can I write tests for code that use this?

    2)Know your audience – this kills me, I mean it gives me GREAT pains with Rhino Mocks and why my use of it is minimal – never assume your audience has worked with a similar framework or really ‘gets’ what the framework is doing conceptually and that all you need is API documentation and a sprinkle of examples with a 2 sentance explanation of what’s going on.

    Rhino Mocks for example: conceptually I know what mocks are for, the benefits, etc., I’ve read every piece of documentation on that website, but can I apply that knowledge using RM? Only after much grief and then my use of it is minimal because it just doesn’t ‘mesh’. I don’t know how else to describe it…it’s cumbersome, kludgey, reminiscent of RPG with that chaining crap, etc…

    Now don’t get me wrong, I *know* in reality it’s very powerful and it’s a matter of experience and someday it will flow like water out of my fingertips (as is this framework) – but it’s turning that learning curve from a mountain with a 900ft cliff face to a bump in the ground that you could barely roll a ball down; that’s the challenge.

    That’s my two cents…since you asked.

  • Jonty

    How do you deal with the fact that certain assemblies do not have references to other assemblies?

    I am calling registries in each assembly like below:

    StructureMapConfiguration.AddRegistry(new BusinessLogicLayer.DependencyInjectionRegistry());

    Then in my BusinessLogicLayer I have:

    protected override void configure() {
    ForRequestedType().TheDefaultIsConcreteType();

    StructureMapConfiguration.AddRegistry(new DataAccessLayer.DependencyInjectionRegistry());
    }

    Is this the correct approach?

  • Frank

    @Jeremy:

    I was just attempting to make the point that cohesion and interclass dependency are orthogonal concepts. A cohesive class may or may not have dependencies on other classes. The same is true for a noncohesive class.

    Cheers,

    Frank

  • http://chadmyers.lostechies.com Chad Myers

    @Kerry:

    Yeah I’d be interested to hear what’s going on there. You can email me firstname.lastname@gmail.com (chad.myers…)

  • Kerry

    @Chad,
    Thanks. It’s not the type of firm, it’s which firm. In the one case, the firm has been edited (but not yet persisted) and we’re trying to make sure all of its clients are updated with the edited properties (may be a smell there, but that’s a requirement at this point).

    In the other case, we want to be sure that the client has the same settings as an already persisted firm.

    If that’s not clear enough, I’ll be more than happy to take it offline – I don’t want to clutter up these comments with it.

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

    @Frank,

    I didn’t mean to imply that “cohesive” automatically means that a class depends on other classes. What I meant was that a class that is cohesive will *have to depend on other classes for services outside the scope of its own cohesive responsibilities*

    The point I was going for is that classes are not monolithic and interact with each other.

  • Frank Smith

    Overall, this is a good article. Just one point… I don’t think you are using the word “cohesive” in the correct way. The concept of cohesion at the class level isn’t related to whether the class depends on other classes or not.

    See also:

    http://javaboutique.internet.com/tutorials/coupcoh/
    http://www.developer.com/java/other/article.php/3327121

    “A cohesive object is one that cannot easily be broken up into multiple objects. It is an object that has one clear purpose and one clear entity that it represents.”

  • http://guyellisrocks.com Guy Ellis

    I haven’t used StructureMap (yet) but that was an excellent explanation of IoC and DI – thanks!

  • http://robinclowers.blogspot.com Robin Clowers

    Hi Jeremy, thanks for this post, it helped me understand exactly what auto wiring is and how it relates to the service locator pattern. Another thing I would like to see is some info on the different config options, especially the fluent API.

  • http://kohari.org/ Nate Kohari

    @Afif

    Ninject is my framework, so naturally I would suggest you check it out. ;)

    However, StructureMap is great, as are other frameworks like Castle Windsor and Autofac, and Jeremy is right in that they are very similar for the simpler cases. However, each has nuances — for example, Ninject provides context during activation, so the activation process is more programmatic and less of a “map lookup”. This lets you do some interesting things depending on state when your instances are being resolved and activated.

    I also haven’t dug too deeply into StructureMap’s internals, so I can’t conclusively say either framework is “better”. I think it comes down to a matter of taste, and you should try each of the different tools and decide which of them feels right to you.

  • http://chadmyers.lostechies.com Chad Myers

    @Kerry: I’m not sure what you’re trying to accomplish here. Why should Employee care what exact type of Firm it has? Doesn’t that violate the Liskov Substitution Principle? Employee should have a Firm. It can be any type of class as long as it derives from Firm.

    I don’t think this problem has anything to do with IoC, so this may not be the best place to ask this kind of question.

    What are you trying to do with the Employee/Firm stuff and how are you using IoC in your project? Maybe that’ll help us understand what you’re up to.

  • Kerry

    We’re still behind the curve a bit on IoC, so I hope a few rather basic questions are tolerable. I’m not sure if we’ll get to use Structure Map per se, but these may help with our general architecture.

    The first thing that comes to mind is how does ObjectFactory know when to use an object that has had state modifications as opposed to a new one? One example I have is a specification we use that compares a base object’s (a “Firm.Type”) property to that of an object of a different type (“Employee.FirmType”).

    When a Firm is edited, we need to modify each one of it’s employees to make sure the types match. However, when an employee is modified, we need to make sure of the same thing (because an employee can be removed from the firm by setting Firm.Type to none).

    So passing in a stateful firm to the Specification is critical when the specification is originated from a firm modification, but we need a new firm from the database when the employee is modified.

    How does IoC handle this?

  • Tom

    Sorry, I don’t know how I could have overlooked that one. Thanks!

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

    Tom,

    I’m writing it as fast as I can. There is existing documentation for StructureMap 2.0 at http://structuremap.sourceforge.net

  • tomdekoning

    Hi Jeremy,

    Where can I find the documentation on structuremap? When I look at http://sourceforge.net/docman/?group_id=104740 there is no documentation available, or am I missing something?

    KR,
    Tom

  • Asa

    Hi Jeremy,
    Forgive my dumb question, but does using an IOC tool mean giving up the New Keyword to initialize objects?

  • Tom

    Hi Jeremy,

    I will be starting today with StructureMap as well. Will let you know if anything is unclear..

    KR,
    Tom

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

    @Afif,

    I purposely avoid looking too deeply at the other IoC tools, so I’m not really the right source. You can use both Windsor and StructureMap w/o any Xml, so that isn’t really unique. I’ve put a bit of effort to make StructureMap more accessible for newcomers, but the biggest part of that effort is probably in the form of (unwritten) documentation.

    Honestly, they’re not that different for the simple things. Just don’t repeat that I said that, okay?

  • http://afifmohammed.blogspot.com Afif

    Jeremy,
    I would be very interested in knowing what are your views on Ninject(another IOC container)? Have you had a chance to look at in any detail? I am fairly across the reasons for using IOC and the benefits it brings, but am yet to dive into a tool, simply because I haven’t had a chance to use it at work, and also a bit reluctant before starting to choose one that has the smallest learning curve and complexity from a user’s perspective. Going by the tutorials ninject seems pretty decent(read: easy to learn), specially with no ‘xml’ configuration files.
    While I imagine your views will be baised with you authoring StructureMap albeit they will still be very helpful.
    - Cheers

  • http://www.blogcoward.com jdn

    @jdm

    Yep. I’m obviously not starting with the most complicated uses of SM, so I expect the API to lead the way, but will send anything if it isn’t obvious.

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

    @John,

    Please feel free to drop me a line if anything is confusing or unclear about the API or in the docs.

  • http://www.blogcoward.com jdn

    This is good stuff, very helpful, especially for people like me who are using StructureMap ‘in anger’ for the first time.

    Thanks.

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

    Another note, It’ll be published in a wider format, so the code getting cut off won’t be quite the same issue