Creating Policies for Setter Injection in StructureMap

One of my continuing goals for StructureMap is to reduce the amount of repetitive configuration code.  A recent trend in OSS .Net projects has been the usage of convention over configuration to eliminate tedious mapping and directive code.  I think it’s a great trend with potential to make us shipping code easier.  Along those lines, StructureMap now allows you to set “policies” (conventions) for which public setters should be injected instead of being forced to specify the policies one single setter at a time.  This is excerpted from http://structuremap.sourceforge.net/ConstructorAndSetterInjection.htm.  Monday’s StructureMap Tip O’ the Day will be the new “BuildUp” functionality that will generally rely on the usage of setter injection policies.

 

New in StructureMap 2.5.2+ is the ability to create setter injection policies. 
What this means is that you create conventions to define which public setter
properties will be mandatory in the construction of objects.  Setter
Injection policies are set with the new “SetAllProperties” method in the
Registry DSL:

               
x.SetAllProperties(policy =>

                {

                   
policy.Matching(prop =>

                   
{

                       
return prop.PropertyType.CanBeCastTo(typeof (IService))

                              
&& !prop.Name.Contains(“Ignore”);

                   
});

                });

In the end, all you’re doing is telling StructureMap that any public Setter that
matches a Predicate<PropertyInfo> policy should be a mandatory Setter.  You
can make multiple declarations inside the
nested closure
for SetAllProperties.  Any additional calls to SetAllProperties() are
purely additive.

In the sections below we’ll look at some helper methods inside
SetAllProperties():


Specify a Setter Policy by Property Name

The sample below will make all public setter properties mandatory where the
property name is suffixed by “Service.”  The call to NameMatches() takes in
a Predicate<string> that is a test against the property name.  The
NameMatches() method just applies a Predicate<string> test against the name of a
public setter.

           
var
container = new
Container(x =>

            {

               
x.SetAllProperties(policy =>

                {

                   
policy.NameMatches(name => name.EndsWith(“Service”));

                });

            });


Specify a Setter Policy by Property Type

Setter injection policies can also be defined by a simple test against the
PropertyInfo.PropertyType.  Here’s the shorthand method:

           
var
container = new
Container(x =>

            {

               
x.SetAllProperties(policy =>

                {

                   
policy.TypeMatches(type => type == typeof (IService));

                });

            });

The “OfType<T>” method is shorthand for:  policy.Matching( property =>
typeof(T).IsAssignableTo(property.PropertyInfo) )

           
var
container = new
Container(x =>

            {

               
x.SetAllProperties(policy =>

                {

                   
policy.OfType<string>();

                   
policy.OfType<IGateway>();

                });

            });

You can also specify that all setter dependencies where the property type is
inside a namespace should be a mandatory setter (this check holds true for
subfolders of a namespace).  This can be handy if you place all services in
a well known namespace.

           
var
container = new
Container(x =>

            {

               
x.SetAllProperties(policy =>

                {

                   
policy.WithAnyTypeFromNamespaceContainingType<ClassWithNamedProperties>();

                });

            });

Here’s another way to specify the namespace:

           
var
container = new
Container(x =>

            {

               
x.SetAllProperties(policy =>

                {

                   
policy.WithAnyTypeFromNamespace(“StructureMap.Testing.Widget3″);

                });

            });


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://codebetter.com/members/jmiller/default.aspx Jeremy D. Miller

    @Mr. Graves,

    I’m sorry, this feature is only in SM 2.5+ and I’ve effectively discontinued any development for .Net 2.0.

    I copied this feature from Ninject I believe. You might see what Nate has for 2.0 support.

  • Mr. Graves

    Can you provide an example of how I could do this without using Lambda functions? I’m writing an app in VS 2005 and I’m trying to do exatly this.