原文地址:http://www.pnpguidance.net/Post/StructureMapTutorialDependencyInjectionIoCNET.aspx
StuctureMap 是一种.NET下的依赖注入框架,希望2.5版早点发布(目前最新是2.4.9)。这篇指南可以帮助您入门。
StructureMap依赖注入基础
在大多数ASP.NET WEB应用程序、智能客户端程序、WPF程序中,你都可以通过提供接口,创建可重用的服务。如:你定义一个接口叫ILogger,这个接口声明一组契约,为你的程序记录日志,并且你做了不同的、可重用的实现这个接口的类,如:类DatabaseLogger,把日志记录到数据库中。
当有一个对ILogger请求的时候,我们可以叫StructureMap注入返回一个DatabaseLogger的实例:
.ForRequestedType < ILogger > ()
.TheDefaultIsConcreteType < DatabaseLogger > ()
.CacheBy(InstanceScope.Singleton);
我们可以使用StructureMapConfiguration类创建一个Singleton模式的DatabaseLogger,也就是在整个应用程序中有且仅有一个实例的DatabaseLogger。
你可以使用StructureMap的ObjectFactory类取出这个ILogger的实例:
StructureMap会返回一个DatabaseLogger的实例,之前我们已经做好了DatabaseLogger对ILogger的映射。
然后把这些代码放到一个最简单的控制台应用程序中:
{
class Program
{
static void Main( string [] args)
{
StructureMapConfiguration
.ForRequestedType < ILogger > ()
.TheDefaultIsConcreteType < DatabaseLogger > ()
.CacheBy(InstanceScope.Singleton);
ILogger logger = ObjectFactory.GetInstance < ILogger > ();
}
}
public interface ILogger {}
public class DatabaseLogger : ILogger {}
}
更精彩的是: StructureMap会自动在对象中注入所依赖的对象实例。比如我们的程序里还有个CustomerDataSource类,也需要ILogger服务:
public class CustomerDataSource : ICustomerDataSource
{
private readonly ILogger _logger;
public CustomerDataSource(ILogger logger)
{
_logger = logger;
}
}
我们把ICustomerDataSource接口的具体实现CustomerDataSource类也注册到StructureMap中,就像刚才的ILogger服务一样:
.ForRequestedType < ICustomerDataSource > ()
.TheDefaultIsConcreteType < CustomerDataSource > ()
.CacheBy(InstanceScope.Singleton);
and then we can ask for an instance of ICustomerDataSource from StructureMap's ObjectFactory Class, which automatically injects the propery ILogger Service into the CustomerDataSource Class' Constructor for us:
然后,我们向StructureMap的ObjectFactory类请求一个ICustomerDataSource的实例,它会自动把ILogger属性注入服务到CustomerDataSource类的构造方法中:
ObjectFactory.GetInstance < ICustomerDataSource > ();
你可以通过下面的控制台程序看到StructureMap是怎样运行的:
using StructureMap.Attributes;
namespace StructureMapTutorials
{
class Program
{
static void Main( string [] args)
{
StructureMapConfiguration
.ForRequestedType < ILogger > ()
.TheDefaultIsConcreteType < DatabaseLogger > ()
.CacheBy(InstanceScope.Singleton);
StructureMapConfiguration
.ForRequestedType < ICustomerDataSource > ()
.TheDefaultIsConcreteType < CustomerDataSource > ()
.CacheBy(InstanceScope.Singleton);
ICustomerDataSource dataSource =
ObjectFactory.GetInstance < ICustomerDataSource > ();
}
}
public interface ILogger { }
public class DatabaseLogger : ILogger { }
public interface ICustomerDataSource { }
public class CustomerDataSource : ICustomerDataSource
{
private readonly ILogger _logger;
public CustomerDataSource(ILogger logger)
{
_logger = logger;
}
}
}
StructureMap注册表
通常依赖注入和控制反转工具都有以组关系注册的方式。StructureMap有”注册表”的概念。我们可以改变上面的代码,把ILogger和ICustomerDataSource放到一组叫ServiceRegistry的类中注册。
using StructureMap;
using StructureMap.Attributes;
using StructureMap.Configuration.DSL;
namespace StructureMapTutorials
{
class Program
{
static void Main(string[] args)
{
StructureMapConfiguration
.AddRegistry(new ServiceRegistry());
ICustomerDataSource dataSource =
ObjectFactory.GetInstance<ICustomerDataSource>();
}
}
public class ServiceRegistry : Registry
{
protected override void configure()
{
ForRequestedType<ILogger>()
.TheDefaultIsConcreteType<DatabaseLogger>()
.CacheBy(InstanceScope.Singleton);
ForRequestedType<ICustomerDataSource>()
.TheDefaultIsConcreteType<CustomerDataSource>()
.CacheBy(InstanceScope.Singleton);
}
}
public interface ILogger { }
public class DatabaseLogger : ILogger { }
public interface ICustomerDataSource { }
public class CustomerDataSource : ICustomerDataSource
{
private readonly ILogger _logger;
public CustomerDataSource(ILogger logger)
{
_logger = logger;
}
}
}
StructureMap PluginFamily和Pluggable特性
如果你愿意使用特性让StructureMap扫描不同的程序集并自动注册不同的类型到你的程序,你可以使用PluginFamily和Pluggable特性:
using StructureMap.Attributes;
using StructureMap.Configuration.DSL;
namespace StructureMapTutorials
{
class Program
{
static void Main( string [] args)
{
StructureMapConfiguration
.ScanAssemblies()
.IncludeTheCallingAssembly();
ICustomerDataSource dataSource =
ObjectFactory.GetInstance < ICustomerDataSource > ();
}
}
[PluginFamily( " Database " , IsSingleton = true )]
public interface ILogger { }
[Pluggable( " Database " )]
public class DatabaseLogger : ILogger { }
[PluginFamily( " CustomerDataSource " , IsSingleton = true )]
public interface ICustomerDataSource { }
[Pluggable( " CustomerDataSource " )]
public class CustomerDataSource : ICustomerDataSource
{
private readonly ILogger _logger;
public CustomerDataSource(ILogger logger)
{
_logger = logger;
}
}
}
结语
这篇文章介绍了些在.NET中使用StructureMap框架依赖注入和控制反转的基础知识。
你也可以试试这些工具:Autofac, Castle Windsor, Ninject, SpringFramework.net, Unity。
希望对您有所帮助,David Hayden。