ObjectBuilder
的系统在运行时注入适当类型的对象的实例(实例有预设的属性)到应用程序中。 ObjectBuilder 的设计
对象实例的构造和释放在绝大多数应用程序是一个通用的过程,尤其是在像使用 Enterprise Library 构建的商业应用程序中。基于这个原因,Enterprise Library 应用程序块利用了一个名为ObjectBuiler
的底层子系统,它执行所有重复、必要的创建对象实例的任务,并提供了高度的灵活性。
ObjectBuilder
封装了对象实例的创建。它可以做下列事情:
创建特定的具体类实例,甚至要求为抽象类型。
如果可以,返回已存在的对象实例;或者总是生成新的实例。
从工厂类中基于配置数据创建合适的对象。
当一个类暴露出多个构造函数时,智能的选择适当的构造函数。
自动应用值到公共属性,并在响应到预定义策略中执行对象的方法。
响应( respond )定义在属性和方法上的属性(Attribute ) ,它影响着新对象的创建和命名。
自动与支持
IBuilderAware
接口的对象通信以指出对象已创建完毕。提供销毁功能,它能由逆向的操作链从已存在的对象中移除设置。
ObjectBuilder
是一个底层次的工具,在绝大多数情况下,不会与其直接在应用程序中交互。在应用程序块中的类使用它在创建声明在应用程序块中的类时生成对象实例。然而,如果你愿意,可以直接在应用程序和框架中使用ObjectBuilder
的特性。也可以创建自己的策略或修改已存在的策略以影响ObjectBuilder
的行为。
关于 ObjectBuilder
的更多信息,包括文档和更新释放,请参见 ObjectBuilder 依赖注入框架。
ObjectBuilder 架构
ObjectBuilder
使用了一个策略管道。利用这个管道,多个操作可以替换为对象被说明和为使用而准备。这儿的意思是可以控制在替换过程中的顺序。它也支持由运行适当的管道进程以相反的顺序的受控的对象释放。
ObjectBuilder
策略在构造和销毁期间管理对象执行的过程。ObjectBuilder
管道被组织成多个阶段,管道的每个阶段包含多个策略。可以实现自己的策略为一个 .NET 框架类,并带有指定的接口。
ObjectBuilder 方法
ObjectBuilder
存在于命名空间 Microsoft.Practices.ObjectBuilder
中,其基类 BuilderBase
暴露了二个方法。BuildUp
方法有二个重载。
例 3.9. C#
BuildUp(locator, type, id, instance, policies[] );BuildUp(locator, id, instance, policies[] );
例 3.10. Visual Basic .NET
BuildUp(locator, type, id, instance, policies() )BuildUp(Of type)(locator, id, instance, policies() )
前面的代码包含下列元素:
- locator
-
这是一个实现了
IReadWriteLocator
接口的类的引用,它为对象或类的放置提供了线索。更多信息请参见此主题后面部分的“使用 ReadWriteLocator ”。 type -
要创建的对象的类型。
id -
分配给新的对象实例的标识。
instance -
可选的到在将起作用管道进程中的已存在的对象实例的引用。这允许使用已存在的对象并确认它们通过管道传送它们以适当的为使用做准备。
ObjectBuilder
仅应用合适的进程到这样的对象实例。 policies[] -
PolicyList
实例的数组,它实现了瞬时的方针( policy ),覆盖了内建的方针。更多信息,请参见本节后面的“使用PolicyList
”。
TearDown
方法利用已存在的对象实例,并在通过策略链后运行它。这个过程可以移除在BuildUp
进程期间添加到对象中的特性,如果打算重新使用对象的话。
TearDown
方法的签名如下。
例 3.11. C#
public TItem TearDown(IReadWriteLocator locator, TItem item)
例 3.12. Visual Basic .NET
Public Function TearDown(Of T)(ByVal locator As IReadWriteLocator, ByVal item As T) As T _ Implements IBuilder(Of TStageEnum).TearDown
使用 ReadWriteLocator
ObjectBuilder
使用生命时间包装器的概念保存对象的引用,这确保正确的对象管理以及在正确的时间销毁它们。定位器引用了生命时间包装器中独立的对象。在定位器中的多个条目可以指向同样的对象实例。例如,在定位器中的条目可能 通过类类型名、它实现的接口和对象名来引用。
定位器可以是只读的或者可读写的,ObjectBuilder
的 BuildUp
方法利用了一个实现了IReadWriteLocator
接口的对象的实例。
使用 PolicyList
PolicyList
是一个政策( Policy )的集合,其中每一个都由实现了IBuilderPolicy
接口的类所描绘,它们一起影响 ObjectBuilder
创建对象的方法。政策可以是临时的也可以是永久的。
临时政策是那些由在ObjectBuilder
中的策略自动生成的或者是通过反射声明在类文件中的方法和属性 ( Property )上的属性 ( Attribute ) 而来的政策。
持久政策是那些由实现了 IBuilderPolicy
接口创建的。可以传递这些类实例的数组到ObjectBuilder
的BuildUp
方法中去。
管道阶段
在 ObjectBuilder
中的管道由下列四个阶段组成:
- 预创建
-
发生在
ObjectBuilder
创建一个对象的新实例前。 创建 -
在此阶段,
ObjectBuilder
创建新的对象实例。 初始化 -
在此阶段,
ObjectBuilder
为使用而准备对象。它设置新对象实例的属性并调用方法。 初始化后 -
此阶段发生在
ObjectBuilder
返回新建的对象前。
表3.1 列出了ObjectBuilder
在管道的每个过程中所完成的默认处理。
表 3.1. 启动一个复合 UI 程序块应用程序的步骤
管道步骤 | ObjetBuilder 策略 |
---|---|
预创建( ProCreation ) | TypeMappingStrategy; SingletonStrategy; ConstructorReflectionStrategy |
创建 ( Creation ) | CreationStrategy |
初始化 ( Initialization ) | PropertySetterStrategy; PropertyReflectionStrategy; MethodReflectionStrategy; MethodExecutionStrategy |
初始化后 ( PostInitialization ) | BuilderAwareStrategy |
应用程序块使用 ObjectBuilder
添加指定的策略到管道中,如果需要,可以添加自己的策略。
策略类型
列出在表3.2 中的用于 ObjectBuilder
的默认策略如下:
- TypeMappingStrategy
-
此策略可以设计对象实质的返回类型。例如,一个抽象或接口类型
IMyObject
的要求是能自动强制转换为具体的类型MyObject
。 SingletonStrategy -
此策略指出
ObjectBuilder
是返回一个新的对象实例还是一个可用的已存在的实例。 ConstructorReflectionStrategy -
此策略检查声明在构造函数中的属性的类,特别是 [InjectionConstructor] 属性,并选择哪一个用于对象的创建。关于在构造函数中用[Dependency] 和 [CreateNew] 属性修饰的参数如何影响行为的更多信息将在本节的后面部分描绘。
CreationStrategy -
此策略实例化新的对象,使用构造函数或者
Activator
类方法。 PropertySetterStrategy -
此策略可以基于政策设置新对象实例的公共属性的值。
PropertyReflectionStrategy -
此策略查检在属性( Property )上的属性( Attribute ) 的类,并应用它们到新的对象实例。拥有[Dependency] 和 [CreateNew] 属性 ( Attribute ) 的属性 ( Property ) 的应用致使这些值注入到了新的对象实例中。
MethodReflectionStrategy -
此策略检查方法上的属性的类,方法必须运行在初始化阶段期间。
MethodExecutionStrategy -
此策略运行新对象实例中的方法,这依赖于政策( Policy )。
BuilderAwareStrategy -
此策略检查类以查看它是否实现了
IBuilderAware
接口。如果实现了,ObjectBuilder
在创建完成时通知对象,然后对象触发 OnBuiltUp 以示准备完毕可以使用了。如果ObjectBuilder
运行了TearDown
方法,它将触发 OnTearingDown 事件。
如果要创建更多的步骤、修改或移除现在的步骤,可以从 BuilderBase
类派生自己的类,而使用自己的步骤,或者预初始化一个构造器以满足自己的需要。查看构造器的源文件( Builder.cs
) 可以看到一个如何做的例子。
基于属性的依赖注入
ObjectBuilder
支持一个能用目的的基于属性的依赖注入。二个内建的策略,ConstructorInjectionStrategy
和 PropertyInjectionStrategy
,提供了依赖注入。二个策略都支持一个通用的属性集,可以应用到变量。这些属性如下:
- [CreateNew]
-
此属性告诉依赖注入系统总是创建新的需要的。这对像模型-视图-控制器(MVC)或模型-视图-展示器(MVP)这样的设计模式非常有用,这些地方创建一个视图就自动生成一个新的控制器/展示器。
[Dependency] -
这是一个通用目的的属性,带有四个可选参数:
- Name
-
指定命名的对象替换未命名的对象。默认值,如果省略的话,是 null ( 未命名的)。
NotPresentBehavior -
指定如果想要的对象不存在的话会发生什么。默认值是 NotPresentBehavior.CreateNew。
CreateType -
指定将要创建的类型。
SearchMode -
指定定位器是否将为对象搜索树,或者消除依赖。如果省略,默认值是Up。
-
前面在 [Dependency] 属性中的这些属性意味着它可以满足下列所有需求:
查找未命名的 X ( X 是一种类型)。如果不存在,将抛出异常。
查找未命名的 X 。如果它不存在,将创建一个新的。
查找未命名的 X 。如果它不存在,提供一个 null 值代替。
查找命名为 Y 的 X ( Y 是一个字符串) 。如果不存在,抛出一个异常。
查找命名为 Y 的 X 。如果不存在,创建一个新的。
查找命名为 Y 的 X 。如果不存在,提供一个 null 值代替。
例如,以下代码总是生成一个类型为 MyCustomObject
的。
例 3.13. C#
using Microsoft.Practices.ObjectBuilder;[Dependency(CreateType=typeof(MyCustomObject), NotPresentBehavior=NotPresentBehavior.CreateNew)]public ICustomObject MyCustomObject { set { ... } }
例 3.14. Visual Basic .NET
Imports Microsoft.Practices.ObjectBuilder_Public WriteOnly Property MyCustomObject() As ICustomObject Set ... End SetEnd Property
如果系统没有找到一个 ICustomObject
它将创建一个新的 MyCustomObject
,并为下一个需要 ICustomObject
的人用ICustomObject
类型注册它。
构造函数、属性和方法注入
三个内建的策略,ConstructorReflectionStrategy
、PropertyReflectionStrategy
和 MethodReflectionStrategy
,使用 [Dependency] 和 [CreateNew] 属性来控制它们的行为。
ConstructorReflectionStrategy
有二个方面。首先,它刻画出所使用的构造函数;第二,它刻画出如何满足那些构造函数的参数。
ConstructorReflectionStrategy
首先查找应用了 [InjectionConstructor] 属性的任何构造函数(在这仅可以是其中之一),如果找到,就使用此构造函数。如果没有应用了[InjectionConstructor] 的构造函数,但仅有一个构造函数,则使用那个构造函数。如果有多个构造函数,但没有任何一个应用了 [InjectionConstructor] 属性,策略将抛出一个异常。
在选择构造函数后,策略将决定如何需要的参数到构造函数,这可能由 [ Dependency ] 或者/ 和 [CreateNew] 属性标记。任何没有应用属性的参数都处理为应用了默认 [ Dependency] 属性(未命名的,NotPresentBehavior= NotPresentBehavior.CreateNew, SearchMode = Up ) 。
PropertyReflectionStrategy
查找带有 [Dependency] 和 [CreateNew] 属性( Attribute )的属性 ( Property )并适当的满足它们(它们必须是公共的并拥有设置器)。在一个类中,它不用没有应用属性( Attribute ) 的属性( Property ) 做任何事件。
MethodReflectionStrategy
查找应用了 [MethodInjection] 的方法,并在初始化阶段执行。这些方法的参数可能包括[CreateNew]和 [Dependency] 属性。任何没有应用属性的参数都将被 为应用了默认的[Dependency] 属性(未命名的,NotPresentBehavior= NotPresentBehavior.CreateNew, SearchMode = Up ) 。
Enterprise Library 属性( Attribute )
Enterprise Library 提供自己的策略到 ObjectBuilder
。这些策略如下:
- ConfigurationNameMappingStrategy
-
此策略读取配置源并转换为
ObjectBuilder
可以使用的格式。 SingletonStrategy -
此策略限制
ObjectBuilder
可以创建的对象实例的数量。 ConfiguredObjectStrategy -
此策略指挥
ObjectBuilder
如何使用配置数据和元数据配置对象。 InstrumentationStrategy -
此策略指定度量仪,如性能计数器,一旦对象创建,
ObjectBuidler
将附加度量到对象上。
这些 ObjectBuidler
策略使用属性正确的创建对象。表1列出了一些最重要的属性。
表 3.2. Enterprise Library 属性 ( Attribute )
属性(Attribute) | 描述 |
---|---|
ConfigurationElementType | 指定 ObjectBuilder 将用于创建对象的配置对象类型。类型必须派生自 NameTypeConfigurationElement ,它与属性类关联。 |
CustomFactoryAttribute | 指定 ObjectBuilder 将用于构建对象的定制工厂类型。 |
ConfigurationNameMapper | 指定用于映射 XML 元素名到提供程序层次中的类型的类型。指定的类型必须实现 IConfigurationNameMapper 接口,ConfigurationNameMappingStrategy 在映射名称时使用此属性来发现要使用的类型。 |
Assembler | 定义构建对象的工厂。 |