Preview of StructureMap’s new Configuration DSL

Mind you, this is strictly a preview.  In fact, I'm hoping to incorporate feedback from this post to improve usability.  I'm adding a new Fluent Interface (think RhinoMocks) DSL to StructureMap vNext for programmatic configuration and wiring.  I see it as an excuse to play with Fluent Interface coding an easier alternative to the attributes or Xml configuration for simpler systems.  I don't necessarily see the DSL as much easier to use than the Xml or Attributes, but I think it is potentially much easier to read and maintain.  The details aren't locked in yet, but you will be able to both bootstrap the StructureMap configuration at application startup and also embed "Registry" classes in assemblies that will be picked up at runtime.  In this release I'm trying to make it much easier to manage StructureMap configuration across multiple assemblies and subsystems for composite applications. 

 

Adding a new Instance

Here are a couple samples of defining new instances in memory.  If you've used StructureMap in the past, notice that you do NOT have to specify the PluginFamily/Plugin configuration separately.  That's now taken care of behind the scenes for easier configuration.

For reference, the constructor for the WidgetRule class looks like this:

    public class WidgetRule : Rule

    {

        private readonly IWidget _widget;

 

        public WidgetRule(IWidget widget)

        {

            _widget = widget;

        }

 

 

        public IWidget Widget

        {

            get { return _widget; }

        }

    }

And here is some samples from the unit tests:

            // Add an instance with properties

            registry.AddInstanceOf<IWidget>()

                .WithName("DarkGreen")

                .UsingConcreteType<ColorWidget>()

                .WithProperty("Color").EqualTo("DarkGreen");

 

            // Specify a new Instance and override the Name

            registry.AddInstanceOf<IWidget>().UsingConcreteType<AWidget>().WithName("MyInstance");

 

 

            registry.AddInstanceOf<IWidget>().UsingConcreteType<AWidget>();

 

            // Specify a new Instance, override a dependency with a named instance

            registry.AddInstanceOf<Rule>().UsingConcreteType<WidgetRule>().WithName("RuleThatUsesMyInstance")

                .UsingNamedInstanceFor<IWidget>("MyInstance");

 

            // Specify a new Instance that specifies the concrete type used for a dependency

            registry.AddInstanceOf<Rule>().UsingConcreteType<WidgetRule>().WithName("DarkGreenWidgetRule")

                .UsingConcreteType<AWidget>().ForDependency<IWidget>();

 

            // Specify a new Instance, create an instance for a dependency on the fly

            registry.AddInstanceOf<Rule>().UsingConcreteType<WidgetRule>().WithName("OrangeWidgetRule")

                .UsingDependency(

                    Registry.Instance<IWidget>().UsingConcreteType<ColorWidget>()

                        .WithProperty("Color").EqualTo("Orange"));

 

            // Build an instance for IWidget, then setup StructureMap to return cloned instances of the

            // "Prototype" (GoF pattern) whenever someone asks for IWidget named "Jeremy"

            registry.AddInstanceOf<IWidget>().WithName("Jeremy").UsePrototype(new CloneableWidget("Jeremy"));

 

            // Return the specific instance when an IWidget named "Julia" is requested

            registry.AddInstanceOf<IWidget>( new CloneableWidget("Julia") ).WithName("Julia");

Adding PluginFamily's

I put this off for years because I initially disliked the PicoContainer bootstrapping model, but people have asked for it.  In one line, here's a quick way to specify the default concrete type for a PluginFamily type.  Please note that this only works for classes that either have no constructor arguments or the types in the constructor argument list are all controlled by StructureMap.

                // Specify the default implementation for an interface

                registry.BuildInstancesOfType<IGateway>().WithDefaultConcreteType<StubbedGateway>();

Now, define the default instance for IWidget in code:

                // Define the default instance of IWidget

                registry.BuildInstancesOfType<IWidget>().AndTheDefaultIs(

                    Registry.Instance<IWidget>()

                        .UsingConcreteType<ColorWidget>()

                        .WithProperty("Color").EqualTo("Red")

                    );

Lastly

I'm also going to add programmatic support for creating Profile's in memory as well to specify application "Modes," i.e. "Connected" or "Disconnected" or "Stubbed."  The programmatic DSL can be used with, or without, Xml or Attribute configuration.  When I make the release, I will write a tutorial on the new DSL grammar and might make a post on the mechanics of writing a Fluent Interface.

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.
  • http://kohari.org/ Nate Kohari

    Very interesting interface! If you’d like to see another .NET EDSL, check out my fledgling IoC container, Titan: http://code.google.com/p/titan-ioc/. It has a fluent interface that controls its contextual binding system.

  • http://miscjibberish.blogger.com Jeremy Wiebe

    I’m doing some C++ work at the moment and was researching a C++ issue I had. In the process I came across this FAQ which talked about “chaining”. Seems very similar to the “Fluent Interface” idea sweeping the C#/.NET community at the moment. :-)

    http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.18