首页 / 软件开发 / .NET编程技术 / Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成
Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成2010-08-18 cnblogs artech在EnteLib中,PIAB(Policy Injection Application Block)和Unity的定位 是轻量级的AOP框架和IoC容器(Container)。通过PIAB,我们可以将一些业务无 关的crosscutting concern定义于相应的CallHandler中,通过Attribute声明或 者配置应用到承载业务逻辑的目标方法上。而通过Unity提供的IoC容器(或者DI 容器),即UnityContainer,很好地实现了依赖的动态注入,从而实现了组件之 间、模块之间或者服务之间的松耦合。Unity完全建立在ObjectBuilder2 之上,顾名思义,这是一个用于创建对象的基础组件。ObjectBuilder2提供了一 种具有高可扩展性的、基于策略(Strategy Based)的对象创建框架,它不仅仅 是Unity的基础组件,也是整个EnterLib和Software Factory的基石。而PIAB通过 方法调用劫持(Method Call Interception)的机制实现了策略注入(Policy Injection)。PIAB提供了不同的方法劫持机制,最为典型的就是基于 TransparentProxy(可以参考我的PIAB系列文章)和代码生成(比如动态生成一 个继承自目标类型的子类,通过Override掉相应的Virtual方法实现策略注入;或 者动态生成一个实现了目标接口的类型,实现相应的方法实现策略注入)。PIAB 需要通过特殊的机制创建可被劫持(Interceptable)对象,而UnityContainer本 质上是一个创建对象的容器,如果能够使UnityContainer按照PIAB的要求创建可 被劫持(Interceptable)对象,那么就能实现两者之间的集成。(Source Code 从这里下载)一、Unity 1.2和EnterLib 4.1如何实现两者的集成我在本系列的第一篇文章就谈过PIAB和Unity之间的集成问题,当时我们是采用了 一个自定以UnityContainerExtension实现的,当时针对的版本是Unity 1.1和 EnterLib 3.1。到了Unity 1.2和EnterLib 4.1,Unity已经被广泛地使用到了整 个EnterLib内部,微软甚至通过Unity对PIAB进行了彻底的改造。所以,最新的 Unity和PIAB中,已经提供了两者的原生集成。Unity和PIAB两者之间的集 成是通过一个特殊的 UnityContainerExtension——Microsoft.Practices.Unity.Intercep tionExtension.Interception实现的。为了演示Interception的使用,我们创建 一个简单的例子。该例子中定义了一服务SyncTimeProvisionService用于实现同 步时间的提供,SyncTimeProvisionService实现了接口ISyncTimeProvision。 SyncTimeProvisionService本身并不提供具体实现,而是通过另一个组件 SyncTimeProvider实现具体的同步时间的返回,SyncTimeProvider实现接口 ISyncTimeProvider。你可以将SyncTimeProvisionService和 SyncTimeProvider看成是一个应用中具有依赖关系的两个模块,为了实现两个模 块之间的解耦,采用基于接口的依赖是推荐的设计模式。所以, SyncTimeProvisionService并不之间依赖于SyncTimeProvider,而是依赖于 SyncTimeProvider的接口ISyncTimeProvider。我们通过Constructor注入实现依 赖注入。为了让读者对Unity和PIAB集成的效果具有一个直观的印象,我在 SyncTimeProvider 上应用了一个CachingCallHandlerAttribute,如果该 CallHandler生效,方法执行的结果将会被缓存,在缓存过期之前,得到的时间将 是一样的。相应的代码如下所示:using System;
namespace Artech.InterceptableUnity
{
public interface ISyncTimeServiceProvision
{
DateTime GetCurrentTime();
}
public class SyncTimeServiceProvisionService : ISyncTimeServiceProvision
{
public ISyncTimeProvider SyncTimeProvider
{ get; private set; }
public SyncTimeServiceProvisionService([Dependency]ISyncTimeServiceProvider syncTimeServiceProvider)
{
this.SyncTimeServiceProvider = syncTimeServiceProvider;
}
#region ISyncTimeServiceProvision Members
public DateTime GetCurrentTime()
{
return this.SyncTimeProvider.GetCurrentTime();
}
#endregion
}
public interface ISyncTimeProvider
{
DateTime GetCurrentTime ();
}
[CachingCallHandler]
public class SyncTimeProvider : ISyncTimeProvider
{
#region ISyncTimeServiceProvider Members
public DateTime GetCurrentTime()
{
return DateTime.Now;
}
#endregion
}
}