StructureMap – Using Attributes

To some degree, StructureMap can be configured through the optional usage of attributes instead of the Xml configuration.  Choosing attributes over Xml configuration is partially a choice of preference.  Before the existence of the Registry DSL, using attributes made the StructureMap configuration more resilient to refactorings when configured classes were renamed or moved into different namespaces or assemblies.  At this point, the advantages of using attributres are largely gone.

Next Prev

Scanning for Classes marked with Attributes

In order to pick up the attributes and add the marked interfaces and classes to the container, StructureMap has to be directed to “scan” one or more assemblies with the Scan() method.

public class ScanningRegistry : Registry { public ScanningRegistry() { Scan(x => { x.Assembly("StructureMap.Testing.Widget"); }); } }

See “Scanning Assemblies” for more information.

[DefaultConstructor] Attribute

The [DefaultConstructor] attribute overrides StructureMap to use a particular constructor function to instantiate a concrete class.

[AttributeUsage(AttributeTargets.Constructor)] public class DefaultConstructorAttribute : Attribute

Without using the [DefaultConstructor] attribute StructureMap will look for the greediest constructor function.

// Force StructureMap to create this class with this constructor [DefaultConstructor] public ProblemView() : this(false) { } public ProblemView(bool showPath) { _showPath = showPath; }

Note:  As of StructureMap 2.5.2, there is also a programmatic way to select constructor functions in the Registry DSL without having to resort to attributes.

[PluginFamily] Attribute

The [PluginFamily] attribute directs StructureMap to register a new PluginType for the decorated type.  It is a shorthand for the <PluginFamily> node in the Xml configuration.  Note that the Xml configuration will override the attribute if both exist for the same CLR type.  The PluginFamily attribute can be used to define any combination of the default instance key, the MementoSource, and the request scope.  [PluginFamily] can be used on any interface, abstract, or concrete class.

public class PluginFamilyAttribute : Attribute
{
private string _default = string.Empty;
private Type _source = null;
private InstanceScope _scope = InstanceScope.PerRequest;
public PluginFamilyAttribute()
{
}
public PluginFamilyAttribute(string DefaultKey)
{
_default = DefaultKey;
}
/// <summary>
/// If set, determines the shared "scope" of the instance -- PerRequest, Singleton, ThreadLocal,
/// HttpContext, etc.
/// </summary>
public InstanceScope Scope
{
get { return _scope; }
set { _scope = value; }
}
/// <summary>
/// If set, specifies the MementoSource for the PluginFamily
/// </summary>
public Type SourceType
{
get { return _source; }
set { _source = value; }
}
/// <summary>
/// Declares the target to be built by StructureMap as a Singleton.  One object instance will
/// be created for each named instance.  Equivalent to saying Scope = InstanceScope.Singleton
/// </summary>
public bool IsSingleton
{
get
{
return _scope == InstanceScope.Singleton;
}
set
{
_scope = value ? InstanceScope.Singleton : InstanceScope.PerRequest;
}
}
}

Here are some sample usages:

[PluginFamily]
public interface IExpirationPolicy

 

/// <summary>
/// Directs StructureMap to use an instance of HTMLSourceMementoSource for the 
/// MementoSource.  Note that the MementoSource specified has to have a
/// no argument constructor
/// </summary>
[PluginFamily(SourceType = typeof(HTMLSourceMementoSource))]
public interface IHTMLSource

 

[PluginFamily(Scope = InstanceScope.HttpContext)]
public interface ImplicitFamilyTarget{}

 

/// <summary>
/// Specifying the default instance is "Default" and marking the PluginFamily
/// as an injected Singleton
/// </summary>
[PluginFamily("Default", IsSingleton = true)]
public interface ISingletonRepository
{
}

[Pluggable] Attribute

When a concrete class is decorated with the [Pluggable] attribute it directs StructureMap to create a Plugin for the concrete type.  StructureMap will “plug” this concrete class into any PluginType where the “Pluggable” class is assignable to the “PluginType” class

/// <summary>
/// Used to implicitly mark a class as a Plugin candidate for StructureMap
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class PluggableAttribute : Attribute

The “Concrete Key” property is required.

[Pluggable("AbsoluteTime")]
public class AbsoluteTimeExpirationPolicy : IExpirationPolicy

If StructureMap controls the construction of all of the constructor argument types of a Plugin class or the constructor has no arguments, the concrete key specified by [Pluggable(“SomeKey”)] is also the instance key.

[Pluggable("Singleton")]
public class SingletonInterceptor : CacheInterceptor
{
private IDictionary _instances;
[DefaultConstructor]
public SingletonInterceptor() : this(new Hashtable())
{
}

In this case, you could retrieve an instance of SingletonInterceptor by callingObjectFactory.GetNamedInstance(typeof(InstanceFactoryInterceptor), “Singleton”).

[SetterProperty] Attribute

StructureMap provides support for Setter Injection.  All properties marked with the [SetterProperty] attribute are mandatory and StructureMap will fail if it cannot find a value for the property at the time of object creation.

[SetterProperty]
public IWidget Widget
{
get { return _widget; }
set { _widget = value; }
}
[SetterProperty]
public FontStyleEnum FontStyle
{
get { return _fontStyle; }
set { _fontStyle = value; }
}
[SetterProperty]
public string ColumnName
{
get { return _columnName; }
set { _columnName = value; }
}
[SetterProperty]
public Rule[] Rules
{
get { return _rules; }
set { _rules = value; }
}
Next Prev