MS 的 Net Framework 2.0的Enterprise Library - November 2005 CTP 和Composite User Interface (UI) Application Block都是依赖于一个核心的组件ObjectBuilder。它同时实现了两个重要的设计模式Service Locator 模式和Dependency Injection 模式,是一个IOC容器。ObjectBuilder可以作为一个IOC框架开发,Enterprise Library - November 2005 CTP的各个模块之间的依赖关系相比较他的以前的版本大大减弱。
“依赖注入”(Dependency Injection)设计模式和 “服务定位器”(Service Locator)设计模式的目标:应该将组件的配置与使用分离开。
"依赖注入”(Dependency Injection)来自IOC容器中,在DotNet底下现在比较著名的就是Castle和Spring.net。依赖注入的形式主要有三种,我分别将它们叫做构造子注入(Constructor Injection)、设值方法注入(Setter Injection)和接口注入(Interface Injection)。 ObjectBuilder实现了构造子注入(Constructor Injection)、设值方法注入(Setter Injection)。
“服务定位器”(Service Locator)模式模式背后的基本思想是:有一个对象(即服务定位器)知道如何获得一个应用程序所需的所有服务。
下面是Object Builder的具体介绍:
Object Builder
The ObjectBuilder is a new subsystem that is shared between Enterprise Library and the Composite User Interface (UI) Application Block. Enterprise Library uses the ObjectBuilder subsystem for tasks such as injecting configuration into block classes and connecting instrumentation classes to application blocks.
The Composite UI Application Block uses a custom underlying system called ObjectBuilder to inject instances of objects of the appropriate type and with preset properties into the application at runtime.
The construction and disposal of object instances is a common process in most applications, and particularly in business applications such as those built using the Composite UI Application Block and the Enterprise Library. For this reason, these blocks take advantage of an underlying sub-system called ObjectBuilder that performs all of the repetitive and necessary tasks for creating object instances, while still providing a high level of flexibility.
ObjectBuilder encapsulates features that simplify the creation of object instances. It can:
ObjectBuilder is a low-level utility that, in most cases, you will not interact with directly in your applications. The classes in the application blocks use it to generate object instances in response to your code creating the classes declared within the application blocks.
However, you can use the features of ObjectBuilder directly in your applications and your own frameworks if you wish. You can also influence the behavior of ObjectBuilder by creating your own strategies or modifying the existing strategies.
Note: |
ObjectBuilder is a patterns & practices Application Block, but - due to the highly specific audience that it tackles and its recent inception - is not yet fully documented as a stand-alone asset like Enterprise Library application blocks or the Composite UI Application Block. |
ObjectBuilder uses a pipeline of strategies that allows multiple operations to take place as objects are instantiated and prepared for use. This allows you to control the order that the processes take place. It also supports controlled disposal of object instances by executing the appropriate pipeline processes in the reverse order.
ObjectBuilder strategies manage the processes performed on objects during construction and disposal. The ObjectBuilder pipeline is organized into stages, and each stage of the pipeline contains multiple strategies. You can implement your own strategies as a .NET class with a specific interface.
ObjectBuilder resides in the namespace Microsoft.Practices.ObjectBuilder, and the base class BuilderBase exposes two methods. The BuildUp method has two overloads:
[C#] |
Copy Code |
BuildUp(locator, type, id, instance, policies[] ); BuildUp<type>(locator, id, instance, policies[] ); |
where:
The TearDown method takes an existing object instance and runs it back through the strategy chain. This process can remove features added to the object during the BuildUp process if you want to re-use the object. You do not have to call the TearDown method on objects that you no longer need to use.
The signature of the TearDown method is:
[C#] |
Copy Code |
TearDown<type>(instance); |
where:
ObjectBuilder uses the concept of a lifetime container to store object references, which ensures the correct management of objects and their disposal at the correct times. Locators reference individual objects within the lifetime container. Multiple locators can point to the same object instance. For example, an object can have separate locators that reference it through the class type-name, the interfaces it implements, and the object name.
Locators can be read-only or read-write, and the BuildUp method of ObjectBuilder takes an instance of an object that implements the IReadWriteLocator interface.
A PolicyList is a set of policies, each represented by classes that implement the ICreationPolicy interface, that together influence the way that an object is created by ObjectBuilder. Policies can be transient or permanent.
Transient policies are those generated automatically by the strategies in ObjectBuilder or through reflection over the attributes on the methods and properties declared in the class file.
Permanent policies are those you create by implementing the ICreationPolicy interface. You can pass an array of these class instances to the BuildUp method in ObjectBuilder.
The pipeline in ObjectBuilder consists of four stages. These are:
Table 1 shows the default processes that ObjectBuilder carries out as each stage of the pipeline:
Pipeline stage |
ObjectBuilder Strategies |
PreCreation |
TypeMappingStrategy SingletonStrategy ConstructorReflectionStrategy |
Creation |
CreationStrategy |
Initialization |
PropertySetterStrategy PropertyReflectionStrategy MethodReflectionStrategy MethodExecutionStrategy |
PostInitialization |
BuilderAwareStrategy |
The application blocks that use ObjectBuilder add specific strategies to the pipeline, and you can add your own strategies if required.
The default strategies for ObjectBuilder listed in Table 1 are:
You can derive your own class from the BuilderBase class if you want to create more stages, modify or remove the existing ones, use your own stages, or pre-initialize a builder to suit your requirements. Looking at the source file for the builder (Builder.cs) provides an example of how this is possible.
ObjectBuilder supports a general-purpose attribute-based dependency injection. Two of the built-in strategies, ConstructorInjectionStrategy and PropertyInjectionStrategy, provide dependency injection. Both of these strategies support a common set of attributes that you can apply to variables:
Name specifies a named object instead of an un-named object. The default if omitted is null (un-named).
The provision of these parameters on the [Dependency] attribute means that it can satisfy all of the following requirements:
For example, this code always generates an object of type MyCustomObject:
[C#] |
Copy Code |
using Microsoft.Practices.ObjectBuilder; [Dependency(CreateType=typeof(MyCustomObject), NotPresentBehavior=NotPresentBehavior.CreateNew) public ICustomObject MyCustomObject { set { ... } } |
If the system cannot find an ICustomObject, it will create a new MyCustomObject, and register it with the type of ICustomObject for the next person who needs an ICustomObject. The default is null.
Three of the built-in strategies, the ConstructorReflectionStrategy, PropertyReflectionStrategy, and MethodReflectionStrategy, use the [Dependency] and [CreateNew] attributes to control their behavior.
The ConstructorReflectionStrategy has two phases. First, it figures out which constructor to use. Second, it figures out how to satisfy those constructor parameters.
The ConstructorReflectionStrategy first looks for any constructor decorated with the [Constructor] attribute (there can be only one of these) and uses this constructor if found. If there is no decorated constructor, yet there is only one constructor, it will use that constructor. If there are multiple constructors but none carries the [Constructor] attribute, this strategy throws an exception.
After selecting the constructor, the strategy determines how to fulfill the requirements of the parameters to the constructor. These may be marked with the [Dependency] and/or [CreateNew] attributes. Any parameter which is undecorated will be treated as though it had been decorated with the default [Dependency] attribute (un-named, NotPresentBehavior= NotPresentBehavior.CreateNew, SearchMode = Up).
The PropertyReflectionStrategy looks for properties with the [Dependency] and [CreateNew] attributes, and satisfies them appropriately (they must be public and have setters). It does not do anything with any undecorated properties on a class.
The MethodReflectionStrategy looks for methods decorated with [MethodInjection], which execute during the initialization phase. The parameters of these methods may contain the [CreateNew] and [Dependency] attributes. Any undecorated parameter is treated as though it had been decorated with the default [Dependency] attribute (un-named, NotPresentBehavior= NotPresentBehavior.CreateNew, SearchMode = Up).
There are five more strategies in place by default in the Composite UI Application Block, as shown in the Table 2. These are in addition to the default strategies implemented within ObjectBuilder.
Pipeline stage |
Composite UI Application Block Strategies |
PreCreation |
TraceSourceStrategy ConfigurationStrategy StateStrategy |
Initialization |
EventBrokerStrategy CommandStrategy |
The strategies listed in Table 2 are:
CAB: http://practices.gotdotnet.com/projects/cab
Entlib:http://practices.gotdotnet.com/projects/entlib