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″);
});
});