Welcome

首页 / 软件开发 / WCF / WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成

WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成2012-10-11 cnblogs Artech在这之前,我写过深入介绍MS EnterLib PIAB的文章(参阅《MS Enterprise Library Policy Injection Application Block 深入解析[总结篇]》),也写过WCF与PIAB的集成(参阅:《WCF后续之旅(8):通过WCF Extension 实现与MS Enterprise Library Policy Injection Application Block 的集成》)、WCF与Unity的集成(参阅《WCF后续之旅(7):通过WCF Extension实现和Enterprise Library Unity Container的集成》)以及Unity与PIAB的集成(参阅《Enterprise Library深入解析与灵活应用(1):通过Unity Extension实现和Policy Injection Application Block的集成》、《Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成》)。由于部分实现时基于EnterLib、Unity前一个版本,在新的版本中(EnterLib V4.1与Unity 1.2)中,MS通过Unity对PIAB进行了重新设计与实现,所以我们很有必要重拾着这个话题,谈谈对于新的EnterLib和Unity,如何将PIAB和Unity集成到WCF之中。

一、设计原理简述

在EnterLib中,PIAB与Unity的定位分别是轻量级的IoC Container(或者DI Container)与AOP框架。PIAB采用Method Call Interception的机制实现了策略的动态注入,其本身依赖于Interceptable对象的创建;UnityContainer建立在ObjectBuilder2之上,本质上是一个用于对象创建的容器。所以,我们可以通过UnityContainer按照PIAB的要求创建Interceptable对象,就能实现Unity与PIAB之间的集成(参阅《Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成》)。

Unity与WCF之间的集成,本质上就是让WCF使用UnityContainer进行服务实例的创建。而WCF框架内部,服务实例的创建同时一个特殊的对象——InstanceProvider。所以我们可以通过自定义InstanceProvider,并借助UnityContainer进行服务实例的提供,那么就能实现Unity与WCF两者之间的集成。所以,创建基于UnityContainer的InstanceProvider是关键。

二、创建基于UnityContainer的InstanceProvider:UnityInstanceProvider

在WCF框架内部,InstanceProvider用户进行服务实例的提供。所有的InstanceProvider实现了接口System.ServiceModel.Dispatcher.IInstanceProvider,下面是IInstanceProvider的定义。服务实例提供实现在GetInstance中,而ReleaseInstance用于实现对服务实例的释放和资源回收。

1: public interface IInstanceProvider
2: {
4: object GetInstance(InstanceContext instanceContext);
5: object GetInstance(InstanceContext instanceContext, Message message);
6: void ReleaseInstance(InstanceContext instanceContext, object instance);
7: }
我们现在的目的就是创建一个基于Unity的InstanceProvider,借助UnityContainer提供对GetInstance方法的实现,我姑且把这个自定义的InstanceProvider称为UnityInstanceProvider。在正式介绍UnityInstanceProvider的具体实现之前,我先介绍一个辅助类型的定义:UnityTypeMapping。

我们知道,UnityContainer采用动态注册接口或者抽象类于具体类型的匹配关系,使得我们可以利用UnityContaner实现基于接口或者抽象类的方式创建我们希望的具体类的对象。UnityTypeMapping用以描述类型的匹配,其定义如下。Type和Mapto分别表示相应的类型(接口或者抽象类)与被匹配的类型(具体类),Name则表示该Mapping Entry的名称(唯一标识)。

1: public class UnityTypeMapping
2: {
3: public Type Type
4: { get; set; }
5:
6: public Type MapTo
7: { get; set; }
8:
9: public string Name
0: { get; set; }
1: }
Unity可以采用编程和配置的方式实现类型的匹配,在真正的系统开发中,后者是首选。为了实现类型匹配配置(UnityTypeElementCollection)到我们定义的UnityTypeMapping列表(IList<UnityTypeMapping>)之间的转化,我定义了下面一个扩展方法(Extension Method):Copy。

1: public static class Extension
2: {
3: public static IList<UnityTypeMapping> Copy(this UnityTypeElementCollection unityTypeElements)
4: {
5: IList<UnityTypeMapping> mappings = new List<UnityTypeMapping>();
6: foreach (UnityTypeElement type in unityTypeElements)
7: {
8: mappings.Add(new UnityTypeMapping { Type = type.Type, MapTo = type.MapTo, Name = type.Name });
9: }
0:
1: return mappings;
2: }
3: }
下面列出了UnityInstanceProvider的具体定义。属性ContractType与Container分别代表服务契约与用于创建服务实例的UnityContainer对象,字段_registeredTypeMapping表示当前UnityContainer相关的类型匹配集合。出于性能的考虑,为了避免UnityContainer的频繁创建和类型匹配关系的频繁解析,我通过两个静态属性|字段来保存它们(Containers和registeredTypeMappings,Key为Container的名称)。在构造函数中接受两个输入参数:contractType与containerName,分别表示服务契约类型与相应UnityContainer的名称。根据containerName判断相应的UnityContainer是否已经创建,如果是,则直接从上述的两个静态变量中提取相应的UnityContainer和类型匹配列表。否则,重新创建UnityContainer,加载相应的配置信息对其进行配置。需要特别指出的是,在对创建的UnityContainer进行初始化的时候,添加了一个特殊的UnityContainerExtension:ExtendedIntercepiton,该UnityContainerExtension用户实现Unity与PIAB的集成,在《Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成》中对ExtendedIntercepiton的实现原理具有详细的介绍。