转-Unity 入门
1. Unity是什么?
Unity是patterns & practices团队开发的一个轻量级、可扩展的依赖注入容器,支持构造函数、属性和方法调用注入.具有如下的特性:
<1>. 它提供了创建(或者装配)对象实例的机制,而这些对象实例可能还包含了其它被依赖的对象实例。
<2>. Unity允许将预先配置的对象注入到类中,实现了inversion of control (IoC)的功能。在Unity中,支持constructor injection(构造器注入), property setter injection(属性设值注入)以及method call injection(方法注入) .
<3>. 支持容器的体系结构。一个容器可以有子容器,允许从子容器到父容器的对象定位查询。
<4>. 可以通过配置文件进行准备和配置容器。
<5>. 不会影响到类的定义(属性设值注入和方法注入除外),这也是轻量级容器的一个体现。
<6>. 支持自定义的容器扩展。
<7>简化了对象的创建,尤其是分层的对象结构和依赖,并简化了应用程序代码。
支持需求的抽象,这允许开发人员在运行时或者配置中指定依赖,并简化了横切关注点的管理。
通过延迟将配置组装到容器来提高灵活性。服务定位功能允许客户代码保存或者缓存容器。这在开发人员可以持久化容器到 ASP.NET Session 或者 Application 中的 ASP.NET Web 应用程序中特别有用。
2.ObjectBuilder是什么
ObjectBuilder是一个可扩展的Application Block,同时也是Unity的基础。最普遍的描述是:ObjectBuilder是“依 赖注入的工具”,还有一种说法是“构建依赖注入容器的框架”,这些多少都有些出入。应该说ObjectBuilder是一个可配置的对象工厂。
3.使用Unity,最基本步骤有三步。
<1>. 建立容器;
<2>. 将接口与类的映射注册到容器中;
<3>. 从容器中解析出正确的对象。
实际操作,step0准备工作,为了测试,建立一个接口以及2个实现类.
{
void Log(string value);
}
public class ConsoleLogger : ILogger
{
#region 成员
public void Log(string value)
{
Console.WriteLine(string.Format("ConsoleLogger:{0}", value));
}
#endregion
}
public class NullLogger:ILogger
{
#region 成员
public void Log(string value)
{
Console.WriteLine("NullLogger:Hey,Nothing to do!");
}
#endregion
}
Step1. 创建容器
在Unity中创建容器实例最简单的方法是直接使用构造函数创建,如下代码所示:
IUnityContainer container = new UnityContainer();
Step2. 注册接口映射
在Unity中提供了一组Register方法供我们在容器中注册接口映射,如下代码所示:
container.RegisterType<ILogger, ConsoleLogger>();
Step3. 获取对象实例
在Unity中提供了一组Resolve方法用以获取对象实例,如下代码所示:
ILogger logger = container.Resolve<ILogger>();
OK,就这么简单!
{
//Step1. 创建容器
Microsoft.Practices.Unity.IUnityContainer container = new Microsoft.Practices.Unity.UnityContainer();
//Step2. 注册接口映射
// container.RegisterType<ILogger, ConsoleLogger>();
container.RegisterType<ILogger, NullLogger>();
//Step3. 获取对象实例
ILogger logger = container.Resolve<ILogger>();
//调用对象方法
logger.Log("Have a look!");
Console.ReadLine();
}
PS:针对不同场景,可进行不同的接口映射注册....其他可保持不变
4.Unity的使用场景主要有以下几个:
建立类型映射
用于单例模式
用于依赖注入
5.建立类型映射
类型映射,为面向对象设计的根本原则——“针对接口编程,而不是针对实现编程”、“要依赖抽象,不要依赖具体类”——在应用中的实现,提供了有力的支持。
我们知道,Unity提供了对象的容器,那么这个容器是如何进行索引的呢?也就是说,容器内的单元是如何标识的呢?在Unity中,标识主要有两种方 式,
一种是直接使用接口(或者基类)作为标识键,
另一种是使用接口(或者基类)与名称的组合作为标识键。键对应的值就是具体类。
用接口类型作为标识键.参照3中例子既是. 用基类类似..
第二种方法:如果需要使用同样的接口(或基类)注册多个映射,可以指定名称来区分每个映射。在需要Resolve的时候,通过指定接口(或基类)与名称的组合作为标识键,就可以获取恰当类型的对象。
如:
{
//Step1. 创建容器
Microsoft.Practices.Unity.IUnityContainer container = new Microsoft.Practices.Unity.UnityContainer();
//Step2. 注册接口映射(指定名称来区分每个映射)区分大小写
container.RegisterType<ILogger, ConsoleLogger>("Tom");
container.RegisterType<ILogger, ConsoleLogger>("jerry");
//Step3. 获取对象实例(结合指定名称)若用tom则报错
ILogger logger = container.Resolve<ILogger>("Tom");
logger.Log("I am tom");
//不同名称获取不同实例
logger = container.Resolve<ILogger>("jerry");
logger.Log("I am jerry!");
Console.ReadLine();
}
6.单例模式
为了实现单例模式,我们通常的做法是,在类中定义一个方法如GetInstance,判断如果实例为null则新建一个实例,否则就返回已有实例。但是 我觉得这种做法将对象的生命周期管理与类本身耦合在了一起,与SRP原则相违背。所以我觉得遇到需要使用单例的地方,应该将生命周期管理的职责转移到对象 容器上,而我们的类依然是一个干净的类。
将Unity应用于单例模式,主要有两种使用场景:
(1)将类型注册为单例
我们可以将一个接口注册为标识键,对应一个具体类。不同的是,要用于单例模式,我们需要使用一个LifetimeManager类型的参数,并指定为ContainerControlledLifetimeManager类型:
RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager())
(2)将已有对象注册为单例
如果我们已经创建了一个对象,并希望使用已创建的对象作为单例,而不是由容器新创建一个对象,那么我们应该使用RegisterInstance方法。以下的代码以接口注册为例,演示了如何使用一个已有对象,为一个接口注册一个具体类,并声明为单例: