StructureMap: Basic Scenario Usage


First, I’m going to assume that you are somewhat already familiar with the concepts of Dependency Injection and what, in general, an Inversion of Control Container is for. If not, you may find these links helpful:

  • http://www.martinfowler.com/articles/injection.html

    I’m also going to assume that you know what I’m talking about when I say “StructureMap”.  If not, then you should check out this link:

     

    If I’ve lost you with any of these assumptions, please leave a comment and I’ll step back and go into these some more for you!

    Most Common Usages

    I’m going to cover three of the more common usage scenarios and how you accomplish these with the upcoming StructureMap 2.5.

    Simple Factory

    I have an interface IFoo with a concrete implementation Foo. When IFoo is requested, new up and return a Foo.

    First, somewhere in the startup code area of your application, register the two types with the container, like so:

    StructureMapConfiguration
    .ForRequestedType<IFoo>()
    .TheDefaultIsConcreteType<Foo>();

    Next, to retrieve the instance elsewhere in your code, use the ObjectFactory class in StructureMap:

    // fooInstance is actually of type Foo
    IFoo fooInstance = ObjectFactory.GetInstance<IFoo>();

     

    Object Lifetime Manager

    I have a session-type object I need kept alive for the entire thread or ASP.NET request.  When IFoo is requested, return me a Foo instance specific to this ASP.NET request or thread

    StructureMap can create an instance of an object for you and manage it’s life time according to the life of the current Thread or, in an ASP.NET scenario, the life of the current HTTP request.  This is useful for caching things like database connection sessions or user credentials, etc.

    First, when you define your object in your startup code, add the CacheBy() option:

    StructureMapConfiguration
    .ForRequestedType<IFoo>()
    .TheDefaultIsConcreteType<Foo>()
    .CacheBy(InstanceScope.HttpContext);

    You can also use InstanceScope.ThreadLocal for non-ASP.NET multithreaded scenarios, InstanceScope.Singleton which means the object will live for the entire life of your AppDomain, and InstanceScope.Hybrid which will choose HttpContext if available, otherwise it’ll revert to ThreadLocal. Hybrid is particularly handy in a unit testing scenario where your tests will automatically adapt to either a live ASP.NET scenario or a test threading scenario.

    Then, request your object just like normal:

    IFoo fooInstance = ObjectFactory.GetInstance<IFoo>();

    If you’ve called GetInstance more than once in that same ASP.NET request, you’ll get the same Foo instance.  If there are two requests executing simultaneously on your web server, they’ll each get their own Foo instance.

     

    Object Assembler

    I have an object that needs to have a value set from the application configuration on startup. When IFoo is requested, new up a Foo, set it’s NumberOfChickens property from the AppSettings/NumChickens setting in my app.config and return me the instance.

    UPDATE 7/26/2008:  My apologies — at the time of this post and updating, StructureMap does not currently set property values unless they have the [SetterProperty] attribute.  The ‘WithProperty’ and ‘SetProperty’ methods are misleading as they apply normally to CONSTRUCTOR parameters by that name OR properties with the [SetterProperty] attribute placed upon them.  There have been several requests for this in the past and there is likelihood the ability to set properties without requiring attributes will be added to the final StructureMap 2.5 release (currently version is 2.4.9).

    Like the previous examples, define your object in your startup code, but change it slightly to have StructureMap automatically take care of getting the property for you:

    StructureMapConfiguration
    .ForRequestedType<IFoo>()
    .TheDefaultIs(
        new ConfiguredInstance()
            .UsingConcreteType<Foo>()
            .WithProperty("NumberOfChickens")
            .EqualToAppSetting("NumChickens")
    );

    Just like the others, the business end is still the same:

    IFoo fooInstance = ObjectFactory.GetInstance<IFoo>();
Project anti-pattern: Many projects in a Visual Studio Solution File