Monday, May 18, 2009

Dependency Injection and StructureMap (4)

In addition to the methods of dependency mapping described in my previous blog, SM provides several other alternative methods to describe the DM.

I use two common methods to specify how instances are created. One is IsThis() and another is ConstructedBy(). The first method takes one parameter as instance and the later one takes function name as parameter. The function returns an instance. Of course, you may create an instance and pass it by the first method. However, the instance must be a none-null instance, while the second method with function may return a null as DM.

For example, if ILog's mapping to instance is a LogToFile class:

public class LogToFile {
public LogToFile(
string file,
TextWriter standardOutput,
TextWriter errorOutput) { ... }
}


In the Registry class' CTOR, the DM then is described as:

internal class SMRegistry : Registry
{
private Configuration _config;
public SMRegistry(Configuration config)
{
_config = config;
ForRequestedType<ILog>().CacheBy(InstanceScope.Hybrid).
TheDefault.Is.ConstructedBy(GetLog);
...
}
private ILog GetLog()
{
ILog instance;
TextWriter writer1 =
_config.StandardOutput ? Console.Out : null;
TextWriter writerErr =
_config.ErrorOutput ? Console.Error : null;
instance = new LogToFile(_config.logFile,
wrtier1, writer2);
return instance;
}
}

where config is an instance of Configuration class which is loaded from an XML file. The LogToFile class CTOR takes a file name as log file name, and additional two TextWriter parameters as standard output and error output. The private function GetLog() is passed to ConstructedBy() to map an instance of ILog.

The above Registry can also be coded in this way:

internal class SMRegistry : Registry
{
private Configuration _config;
public SMRegistry(Configuration config)
{
_config = config;
ForRequestedType<TextWriter>.CachedBy(InstanceScrop.Hybrid).
TheDefault.Is.ConstractedBy(GetTW()).
WithName(LogToFile.StandardOutPutName);
ForRequestedType<TextWriter>.CachedBy(InstanceScrop.Hybrid).
TheDefault.Is.IsThis(Console.Error).
WithName(LogToFile.ErrorName);
ForRequestedType<ILog>().CacheBy(InstanceScope.Hybrid).
TheDefault.Is.OfConcreteType<LogToFile>().
ConstructedBy(GetLog);
...
}

private ILog GetLog()
{
return new LogToFile(_config.LogFile,
ObjectFactory.GetNamedInstance<TextWtiter>(
LogToFile.StandardOutPutName),
ObjectFactory.GetNamedInstance<TextWtiter>(
LogToFile.ErrorName));
}

private TextWriter GetTW()
{
return
_config.StandardOutput ? Console.Out : null;
}
}

This example shows how to use IsThis() method for an instance. LogToFile.StandardOutputName and LogToFile.ErrorName are constants defined within LogToFile class.

Here you can see SM's Registry DSL provides much flexible way to describe DMs.

0 comments: