WCF后续之旅(8):通过WCF Extension 实现与MS Enterprise Library Policy Injection Application Block的集成
在上一篇文章中,我们通过自定义InstanceProvider实现了WCF和微软Enterprise Library Unity Application Block的集成,今天我们已相同的方式实现WCF与Enterprise Library的另一个Application Block的集成:Policy Injection Application Block (PIAB)。
PIAB,通过Method Interception的机制实现了AOP(Aspect Oriented Programing)。按照PIAB的编程方式,我们将非业务逻辑,比如Caching、Authorization、Transaction Enlist、Auditing、ExceptionHandling扽等等, 定义在一个个的CallHandler,这些CallHandler通过Attribute或者Configuration的方式应用到目标方法上。
由于PIAB特殊的实现机制(PIAB实现原理),我们需要通过PIAB的PolicyInjector来创建新的对象或者包装现有的目标对象。只有调用这种能够方式的对象,应用在上面的CallHandler才能被执行。所以WCF和PIAB的核心问题就是如何通过PIAB PolicyInjector来创建新的Service Instance,或者包装已经生成的service instance。在上面一篇文章中,我们通过Unity Container重新定义了InstanceProvider,我们今天的实现方案也是通过自定义InstanceProvider的方式来实现,不是我们需需要通过PolicyInjector来进行对象的创建。
1、创建基于PolicyInjection的InstanceProvider
下面是我们新的InstanceProvider(PolicyInjectionInstanceProvider )的定义
namespace Artech.WCFExtensions
{
public class PolicyInjectionInstanceProvider : IInstanceProvider
{
private Type _serviceContractType;
private string _policyInjectorName;
public PolicyInjectionInstanceProvider(Type serviceContractType, string policyInjectorName)
{
this._serviceContractType = serviceContractType;
this._policyInjectorName = policyInjectorName;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, Message message)
{
PolicyInjector policyInjector = null;
if (string.IsNullOrEmpty(this._policyInjectorName))
{
policyInjector = new PolicyInjectorFactory().Create();
}
else
{
policyInjector = new PolicyInjectorFactory().Create(this._policyInjectorName);
}
Type serviceType = instanceContext.Host.Description.ServiceType;
object serviceInstance = Activator.CreateInstance(serviceType);
if (!this._serviceContractType.IsInterface && !serviceType.IsMarshalByRef && policyInjector is RemotingPolicyInjector)
{
return serviceInstance;
}
return policyInjector.Wrap(serviceInstance, this._serviceContractType);
}
public object GetInstance(InstanceContext instanceContext)
{
return this.GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
IDisposable disposable = instance as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
#endregion
}
}