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.