Sunday, May 10, 2009

Dependency Injection and StructureMap (2)

As I mentioned in my previous blog, Registry DSL is a recommended way to configure DI mappings by StuctureMap. StructureMap introduces Registry class which is normally used as a base class for customizing DI mapping definitions.

To start up, you need to define a class with Registry class as base. In the class' constructor, what you need to do is just to define dependencies. In StructureMap terms, the dependencies are defined as mapping PluginFamilies to Plugins. PluginFamilies are normally interfaces, but they can be any classes. Plugins, on the other hand, are plug-able classes corresponding to PluginFamily interfaces or classes. Here is a simple example:

internal class SMRegistry : Registry
{
public SMRegistry()
{
ForRequestedType<IProcessController>().
CacheBy(StructureMap.Attributes.InstanceScope.Singleton).
TheDefault.Is.OfConcreteType<Processcontroller>();
}
}

As you can see, the pattern is very simple and easy to read: for a required interfase or class, specify a cache mechanism, and the mapped class. StructureMap uses Fluent Interface patten to define dependencies. The above codes map IProcessController interface to a concrete class ProcessController. This class is ready for use. As in my previous blog example, the class can be loaded as a Registry instance by ObjectFactory.Add() method.

After the loading, SM has the knowledge of how to create concrete class ProcessController for IProcessController. You would not need to worry about when and how to create the concrete instance in your application. SM and Registry takes care of when and how. Since interfaces are used in your application, the application does not aware the implementation classes and what they are. This decoupling strategy allows you to focus on business logic implementation and makes it so easy to to update implementation libraries or to plug in a different implementation class without compiling your whole application. To update or fix bugs implementation classes or libraries, only those classes or libraries need to be compiled; to plug in different implementations, only the customized Registry class or libraries need to be recompiled.

The above example is based on the assumption that the class PocessController has only one default construtor, i.e., the constructor with no parameters. How about the cases with parametrized CTOR? SM provides similar Fluent Interface APIs for you.

For example, the following codes show the ProcessController class' CTOR with several parameters, and a LogToFile class which is used as a parameter:

public class ProcessController : IProcessController
{
public ProcessController(
int id,
ILog log,
IDataReader dataReader,
IDataProcessor dataProcessor,
IDataWritter dataWriter)
{ ... }
...
}
public class LogToFile : ILog
{
public LogToFile(
string file,
string flags)
{...}
...
}

I'll show you how to use SM to define their dependencies in a Registry class in the next blog.

0 comments: