现在的位置: 首页 > 综合 > 正文

使用 Unity Application Block(三):理解和使用依赖注入的键

2012年08月14日 ⁄ 综合 ⁄ 共 5711字 ⁄ 字号 评论关闭

在使用 Unity 创建对象之前,需要准备 Unity 容器,也即进行注册(类型映射)。在 使用Unity(二):配置 Unity 、读取配置信息和获取对象中, 我们学习了如何使用配置文件来进行注册,而在本文中,我们将学习使用代码来进行各种注册,这些代码所实现的功能同样可以使用配置文件来实现。

因为 Unity 自带的文档已在这方面进行了详细说明,所以在此仅对该文档进行了翻译,以下是译文。

Unity
应用程序块容器用键以及可选的名称来标识注册(类型映射)。键是接口一个接口或者一个类(通常是基类)的类型名称,它决定了实现或继承的具体对象的类型。
此键标识了映射,所以容器可以在对 Get 或者 GetAll
的调用的响应中获取具体的对象类型。在有多个针对同一类型的地方,可选的名称用以区分这些映射,并允许代码指定将使用类型的哪个映射。

本主题的下列章节描述了可以如何使用依赖注入的键: 

  • 用接口的类型做为依赖键
  • 用对象类型名称做为依赖键
  • 组合依赖键和注册名
  • 用于单件对象的依赖键
  • 用于已有对象和 BuildUp 方法的依赖键
  • 通过依赖键获得所有注册类型的列表

用接口类型做为依赖键

做为使用接受接口类型名称的 Register 和 Get 方法的重载的示例,下列代码注册了一个用于 IMyObject
接口的映射,并指定容器将返回 MyRealObject 类的实例(它实现了 IMyObject 接口)。在这种情况下,注册键是
IMyObject。随后使用键 IMyObject 请求实例的代码将接收到一个 MyRealObject
类的实例。此示例使用了容器方法的泛型重载。

IUnityContainer myContainer = new UnityContainer();
myContainer.Register
<IMyObject, MyRealObject>();
IMyObject myRealObjectInstance 
= myContainer.Get<IMyObject>();

另一种方法就是,可以使用未泛型的方法重载。下列代码将得到同样的结果。

IUnityContainer myContainer = new UnityContainer();
myContainer.Register(
typeof(IMyObject), typeof(MyRealObject));
IMyObject myRealObjectInstance 
= myContainer.Get(typeof(IMyObject));

注意:前面的二个 Unity 容器的泛型和非泛型重载确保 Unity
应用程序块可以在不支持泛型的语言中使用。可以在代码中使用任意一种方法(泛型和非泛型的重载),以及根据需要混合使用它们。例如,可以使用泛型重载注册
映射,然后使用非泛型重载获取对象实例,返过来也是一样的。

用对象类型名称做为依赖键

在需要注册用于基类或者其他对象类型(不是接口)的映射时,可以使用接受对象类型名称的 Register 和 Get 方法的重载,它们不使用泛型代码语法。下列示例展示了接受对象类型名称做为键的 Register 和 Get 方法的重载的使用。

下 列代码注册了一个用于 MyBaseObject 对象的映射,并指定容器将返回一个 MyRealObject 类的实例(它继承自
MyBaseObject 类)。在这种情况下,注册键是 MyBaseObject。随后使用键 MyBaseObject
请求实例的代码将接收到一个 MyRealObject 类的实例。

IUnityContainer myContainer = new UnityContainer();
myContainer.Register
<MyBaseObject, MyRealObject>();
MyBaseObject myRealObjectInstance 
= myContainer.Get<MyBaseObject>();

另一种方法是,可以使用方法的非泛型重载。下列代码可以获得同样的结果。

IUnityContainer myContainer = new UnityContainer();
myContainer.Register(
typeof(MyBaseObject), typeof(MyRealObject));
MyBaseObject myRealObjectInstance 
= myContainer.Get(typeof(MyBaseObject));

组合注册键和依赖名称

如果需要使用同样的名称注册多个映射,就可以指定对象的名称来区分每个映射。然后,指定名称做为键来
要获取适当类型的对象。下列代码示范了可以如何注册二个用于同样接口类的映射,然后容器根据在调用的 Get
方法中指定的键和名称来返回适当的对象类型。此示例使用了容器方法的泛型重载(同样也可以使用用对象类型而不是接口的依赖键的非泛型方法)。

// Create container and register types
IUnityContainer myContainer = new UnityContainer();
myContainer.Register
<IMyObject, MyFirstObject>("One");
myContainer.Register
<IMyObject, MySecondObject>("Two");

// Get an instance of each type
IMyObject myFirstInstance = myContainer.Get<IMyObject>("One");
IMyObject mySecondInstance 
= myContainer.Get<IMyObject>("Two");

注意:注册(映射)名称是一个字符串,如果需要,可以包含空格。任何时候,它们是大小写敏感的。例如,名称“Mymapping”和“MyMapping”将指的是二个不同的注册映射。

下列代码示范了可以如何使用接受类型名称的 Register 和 Get
方法的重载来注册用于同一基类或其他类的二个映射,然后容器根据在调用的 Get
方法中指定的键和名称返回适当的对象类型。此示例使用了容器方法的非泛型重载(同样也可以使用用对象类型而不是接口的依赖键的泛型方法)。

// Create container and register types
IUnityContainer myContainer = new UnityContainer();
myContainer.Register(
typeof(MyBaseObject), typeof(MyFirstObject), "One");
myContainer.Register(
typeof(MyBaseObject), typeof(MySecondObject), "Two");

// Get an instance of each type
MyBaseObject myFirstInstance = myContainer.Get(typeof(MyBaseObject), "One");
MyBaseObject mySecondInstance 
= myContainer.Get(typeof(MyBaseObject), "Two");

用于单件对象的依赖键

在需要目标对象是一个单件实例时,可以使用 SetSingleton 方法来注册在容器中的类型映射。在此有接受接口或者类型名称做为键的 SetSingleton 方法的重载,还可以接受一个名称以区分使用同样的键的多个映射。

下列代码展示了可以如何使用接口做为键或者使用类型名称做为键来注册单件,以及在使用同样的键的多个注册的地方提供可选的名称。此示例同时使用了容器方法的泛型和非泛型重载,并展示了如何在注册映射和获取对象实例时混合使用它们。

// Create container and register singletons
IUnityContainer myContainer = new UnityContainer();
myContainer.SetSingleton
<MyObject>();
myContainer.SetSingleton
<MyObject>("One");
myContainer.SetSingleton(
typeof(MyObject), "Two");
myContainer.SetSingleton(
typeof(MyObject));
myContainer.SetSingleton
<MyObject>("One");
myContainer.SetSingleton(
typeof(MyObject) "Two");

// Get the single instance of each type
IMyObject mySingleton = myContainer.Get(typeof(MyObject));
IMyObject myFirstSingleton 
= myContainer.Get<MyObject>("One");
IMyObject mySecondSingleton 
= myContainer.Get<MyObject>("Two");

MyObject mySingletonObject = myContainer.Get(typeof(MyObject));
MyObject myFirstSingletonObject 
= myContainer.Get(typeof(MyObject), "One");
MyObject mySecondSingletonObject 
= myContainer.Get<MyObject>("Two");

用于已有对象和 BuildUp 方法的依赖键

Unity 容器暴露了 RegisterInstance 方法的重载,它允许注册依赖注入映射,然后返回单个已有对象实例的引用。这些方法中的每一个都接受标识对象接口或者类型的依赖键,和已有的对象实例。在多个注册使用同样的键的地方,还可以可选的提供一个名称。

Unity 容器还暴露了 BuildUp 方法的重载,它允许在需要时直接应用依赖注入到一个对象。BuildUp 方法的重载接受一个已有对象实例的引用。在多个注册的对象使用同样的键的地方,还可以可选的提供一个名称。

如何用依赖键使用 RegisterInstance 和 BuildUp 方法的细节,请参见理解和使用已有的对象实例。

通过依赖键获取所有注册类型的列表

在 要获得指定类型的所有注册对象的列表时,可以使用 GetAll
方法。此方法有二个重载,分别接受接口或者类型名称,并返回包含指定类型的所有注册对象的引用的 IEnumerable
的实例,但不包括默认映射。由 GetAll 方法返回的列表仅包括命名的实例注册。 

注意:如果要能获取一个映射类型的列表,记得必须除使用类型(依赖键)之外还要使用名称来注册类型映射
是很重要的。换句话说,必须使用除依 赖类型之外还接受名称(string 类型)的 Register、SetSingleton 和
RegisterInstance 方法的重载。

下面的示例展示了可以如何获取用于指定依赖键的注册类型的列表。

// Create container and register types using a name for each one
IUnityContainer myContainer = new UnityContainer();
myContainer.Register
<IMyObject, MyDefaultObject>();
myContainer.Register
<IMyObject, MyFirstObject>("One");
myContainer.Register
<IMyObject, MySecondObject>("Two");

// Get an list of non-default types registered for IMyObject
// List will only contain the types MyFirstObject and MySecondObject
IEnumerable<IMyObject> objectList = myContainer.GetAll<IMyObject>();

另一种方法是,可以使用容器的非泛型方法来获得同样的结果,除了此时的返回值是 Object 类型的 IEnumerable 列表以外。

// Create container and register types using a name for each one
IUnityContainer myContainer = new UnityContainer();
myContainer.Register(
typeof(MyBaseObject), typeof(MyDefaultObject));
myContainer.Register(
typeof(MyBaseObject), typeof(MyFirstObject), "One");
myContainer.Register(
typeof(MyBaseObject), typeof(MySecondObject), "Two");

// Get an list of non-default types registered for MyBaseObject
// List will only contain the types MyFirstObject and MySecondObject
IEnumerable<MyBaseObject> objectList = myContainer.GetAll(typeof(MyBaseObject));

关于 Unity 的方法的详细使用方法,请继续关注我的理想&美人

希望对您有所帮助!

邓明

抱歉!评论已关闭.