Index

Now that we can control the lifecycle of an instance it’s worth considering how those instances are constructed. In the code shown so far the parameter-less Use method is responsible for specifying the concrete type. Using this overload will cause StructureMap to create instances using the type constructor. This will cover many scenarios but there will be cases where you will need more control over how instances are constructed. For these scenarios StructureMap provides a number of overloads for Use.

The simplest scenario is that we wish the container to always supply an instance we already have. This is almost illegally simple:

var existingInstance = new ExistingInstance();
ObjectFactory.Initialize(initialise =>
	{
		initialise.For<IExistingInstance>().Use(existingInstance);
	});

The container will now return the specified instance. This has an implication on the lifecycle. As we’ve specified the instance to return we get Singleton behaviour. To demonstrate the code:

var firstExistingInstance = ObjectFactory.GetInstance<IExistingInstance>();
var secondExistingInstance = ObjectFactory.GetInstance<IExistingInstance>();

Console.WriteLine(string.Format("Existing instances are the same: {0}", ReferenceEquals(firstExistingInstance, secondExistingInstance)));

Produces the output:

 image

This is unlike the default behaviour when we specify the type not the instance where StructureMap will create a new instance for every call to GetInstance<T>. It is therefore important that any instance registered in the container in this fashion be threadsafe when used in a multi-threaded environment.

Being able to use an existing instance is helpful but we will also have situations where we need to specify the mechanism used to construct a new instance. This allows us to use lifecycles other than Singleton as well as having control over instance construction. For this purpose StructureMap provides two overloads to Use that take Func delegates. By supplying a lambda or method to one of these overloads we can specify the code to be used to generate instances.

The simpler method takes a Func<T> (where T is the plugin type). Its usage is straightforward:

initialise.For<IDynamicItem>().Use(() => new DynamicItem());

We can also specify constructor parameters:

initialise.For<IDynamicItem>().Use(() => new DynamicItem("Some Parameter"));

Or a method that matches the Func<T> signature:

initialise.For<IDynamicItem>().Use(DynamicItemFactory.CreateItem);

In short we can do all the normal things that are supported for Func<T> arguments to a method.

The more complex method takes a Func<IContext, T> and is useful for scenarios where the construction process needs to consider the context in which the instance is being created. This is useful for advanced scenarios that will be described later in this series. However I will note here that IContext supports GetInstance<T> making this the overload to use when you are manually constructing an instance that has dependencies you wish to obtain from the container. For example:

initialise.For<IDependentDynamicItem>().Use(context => new DependentDynamicItem(context.GetInstance<IDynamicItem>()));

Before this part of the series ends it’s worth considering the behaviour of the standard parameter-less Use method we’d been using prior to this article. This overload causes StructureMap to use a constructor on the type to create instances. If there is only a single constructor then it is obvious which constructor to use. However things are not always this simple. There are a few things to consider in how StructureMap selects the constructor to use.

The first thing to note is that StructureMap will only consider public constructors. A type with no public constructors cannot be handled and will result in a StructureMapException. If you need to use a type with no public constructors with StructureMap then you must use the Use overloads discussed in this post.

Of the public constructors StructureMap will pick that which has the most arguments. This is done on the general assumption that the constructor with the most arguments will supply the greatest number of dependencies to the instance. In the event that there are multiple constructors that match this criteria StructureMap will pick the first it encounters. In such scenarios it is probably best to eliminate the excess constructors in order to ensure certainty and reduce confusion. Where this is not possible (for instance if the type is supplied by an external library) taking over construction using a Use overload as described above should be seriously considered. The alternative is to rely on behaviour that is liable to change if StructureMap, the external library are updated.

Now that we can control both the construction and lifecycle of instances the next post in this series will describe how we can make most of the configuration we’ve done so far unnecessary.