Microsoft 的 P&P 团队在 12 日发布了 Unity 的社区预览版,大家可以在 Unity 的站点上查看它的最新信息。
从今天开始,我将和大家一起来学习这个控制反转(Inversion of Control, IoC) 和依赖注入(Dependency Injection, DI) 容器的使用。关于 IoC 和 DI,大家可以参考 Martin Fowler 著的《IoC 容器和 Dependency Injection 模式》。
描述
Unity 应用程序块(Unity)是一个轻量级、可扩展的依赖注入容器,支持构造函数、属性和方法调用注入。它为开发人员提供了如下好处:
- 简化了对象的创建,尤其是分层的对象结构和依赖。
- 允许开发人员在运行时或者配置中指定依赖的需求抽象,以及简化了横切关注点的管理。
- 服务定位功能允许客户代码保存或者缓存容器。这在开发人员可以持久化容器到 ASP.NET Session 或者 Application 中的 ASP.NET Web 应用程序中特别有用。
常见场景
除了单独解决横切关注点如日志、认证、授权、缓存和异常处理的组件以外,现代业务系统通常由定制的业务对象和在应用程序中完成特殊的或者一般的任务的组件组成。
成功构建这样的应用程序的关键是获得解耦的或者极度松耦合的设计。松耦合的应用程序更加灵活、更加易于维护。同时在开发期间进行测试,可以模拟对象的桩(轻量级模拟的实现),这增强了实质的依赖。例如,数据库连接、网络连接、ERP 连接和富用户接口组件。
依赖注入是一种用于构建松耦合应用程序的主要技术。它提供了处理对象间依赖的方法。例如,一个处理用户信息的对象可能依赖于访问数据存储、验证信息和检查 用户是否被授权执行更新的其他对象。依赖注入技术可以确保用户类正确的初始化及组装所有这些对象,特别是依赖是抽象的地方。
使用容器可以有很多好处,但它会改变应用程序的设计方式,尤其适合于基于组件的开发,朋友们可以有选择的使用它。
最基本的代码
下面的代码展示了 Unity 容器的最基本的使用方法。
IUnityContainer myContainer
=
new
UnityContainer();
myContainer.Register
<
IMyObject, MyRealObject
>
();
IMyObject myRealObjectInstance
=
myContainer.Get
<
IMyObject
>
();
在上面的代码中,首先使用容器的 Register 方法注册了一个 IMyObject 接口到 MyRealObject 具体类的类型映射(注:映射还可以通过配置文件来进行指定),然后通过 Get 方法来获取 IMyObject 接口的默认映射所对应的具体对象实例。在这里,IMyObject 接口被做为映射的键,Get 方法通过它来查找注册的具体类的实例。
构造函数注入的代码示例
假如,我们有如下的类定义:
public
class
MyObject {
public
MyObject(MyDependentClass myInstance) {
myInstance.UserName
=
myInstance.ToString();
Console.WriteLine(
string
.Format(
"
My name is {0}.
"
, myInstance.UserName));
}
}
然后,利用容器,就可以这样来实例化 MyObject 类的对象:
IUnityContainer uContainer
=
new
UnityContainer();
MyObject myInstance
=
uContainer.Get
<
MyObject
>
();
Unity 容器会自动为 MyObject 对象创建 MyDependentClass 类的实例。
属性(设置器)注入的代码示例
例如,我们有如下的类定义:
public
class
MyObject {
private
SomeOtherObject _dependentObject;
[Dependency]
public
SomeOtherObject DependentObject {
get
{
return
_dependentObject; }
set
{ _dependentObject
=
value; }
}
}
然后,使用与构造函数注入同样的实例化代码,Unity 容器就会自动为 MyObject 对象创建 SomeOtherObject 的对象实例。
IUnityContainer uContainer
=
new
UnityContainer();
MyObject myInstance
=
uContainer.Get
<
MyObject
>
();
Console.WriteLine(
string
.Format(
"
Property injection object is {0}.
"
,myInstance.DependentObject) );
Unity 应用程序块的特性
- 它提供了用于构建(或者组合)对象实例的机制,对象可能包含其他依赖的对象实例。
- 它暴露了支持使用映射和对象(包括单件(singleton)实例)配置容器的 Register 方法,以及返回可以包含任何依赖的对象的构建对象实例的 Get 方法。
- 通过允许注入预配置的对象到由程序块构建的类中来提供控制反转(IoC)功能。开发人员可以在构造函数中指定接口或者类的类型(构造函数注入),或者用特性装饰属性和方法以初始化属性注入和方法调用注入。
- 提供了用于容器的继承层次。容器可能有子容器,允许将对象定位查询从子容器传递到父容器中。
- 可以从标准配置系统如 XML 文件中读取配置信息,并使用它来准备和配置容器。
- 不需要对象类的定义。不需要使用特性来装饰类(使用属性或者方法调用注入除外),无限制的类声明。
- 支持开发人员可以实现的自定义容器扩展。例如,允许其他对象构建方法和容器特性,如缓存。
代码下载
在这里,可以下载本文的示例代码。