扩展WCF自定义行为(二)

WCF运行时扩展实践
本文介绍如何通过自定义参数检查器和操作调用器扩展WCF服务的行为,包括参数验证和服务结果缓存。

上一篇文章中介绍了WCF运行时体系结构及客户、服务器端的扩展点。下面以一个简单的Demo来演示扩展WCF的运行时行为。源代码下载

假设有一个WCF服务接口,提供以用户名进行用户身份编号的查询。


[ServiceContract] 
    
public   interface  IIdentityService
    {
        [IdentityValidate]
        [IdentityCache] 
        [OperationContract]
        
int  GetIDByName( string  name);
}

[ServiceContract]

    
public interface IIdentityService

    {

        [IdentityValidate]

        [IdentityCache]

        [OperationContract]

        
int GetIDByName(string name);

}

一,自定义参数检查器

假设业务规则要求IIdentityService服务接口的用户名参数不能为空,且必须不少于3个字符。在这种情况下,我们需要在服务器端进行参数检查,此检查在服务接口操作(GetIDByName)调用前执行,如果参数检查不通过,抛出异常,终止执行后续的操作调用。自定义参数检查器都实现IParameterInspector接口。该接口定义两个方法:AfterCallBeforeCall,分别是在服务接口操作调用前和调用后进行参数检查。


public   class  NameInspector : IParameterInspector
    {
        
int  identityParamIndex;

        
public  NameInspector() :  this ( 0 ) { }

        
public  NameInspector( int  ParamIndex)
        {
            
this .identityParamIndex  =  ParamIndex;
        }

        
#region  IParameterInspector Members

        
public   void  AfterCall( string  operationName,  object [] outputs,  object  returnValue,  object  correlationState)
        {
        }

        
public   object  BeforeCall( string  operationName,  object [] inputs)
        {
            
string  Param  =  inputs[ this .identityParamIndex]  as   string ;
            
if  (Param == null || Param .Length  < 3 )
                
throw   new  FaultException( " Invalid name.  " );
            
return   null ;
        }

        
#endregion
}

同时,可以定义一个申明标签来添加这个自定义参数检查器到WCF的运行时行为中。该标签实现IOperationBehavior接口。


public   class  IdentityValidateAttribute : Attribute, IOperationBehavior
    {
        
#region  IOperationBehavior Members

        
public   void  AddBindingParameters(OperationDescription operationDescription,
            BindingParameterCollection bindingParameters)
        {
        }

        
public   void  ApplyClientBehavior(OperationDescription operationDescription,
            ClientOperation clientOperation)
        {
            NameInspector nameInspector 
=   new  NameInspector();
            clientOperation.ParameterInspectors.Add(nameInspector);
        }

        
public   void  ApplyDispatchBehavior(OperationDescription operationDescription,
            DispatchOperation dispatchOperation)
        {
            NameInspector nameInspector 
=   new  NameInspector();
            dispatchOperation.ParameterInspectors.Add(nameInspector);
        }

        
public   void  Validate(OperationDescription operationDescription)
        {
        }

        
#endregion
    }

 

二,  自定操作调用器

假设IIdentityService服务接口需要频繁地被调用、而且每次调用的服务端资源开销比较大。在这种情况下我们希望在服务端操作调用中缓存服务调用的结果。自定义一个服务端操作调用器,该操作调用器实现IOperationInvoker接口,并在Invoke方法中使用了调用结果缓存功能。Invoke方法首先尝试在其缓存中查询参数对应的结果,如果找到则直接返回该结果,如果找不到缓存结果则调用默认的操作调用器获取结果并缓存该结果。


public   class  IdentityCaching : IOperationInvoker
    {
          IOperationInvoker innerOperationInvoker;
        Dictionary
< string int >  identityCache  =   new  Dictionary < string int > ();

        
public  IdentityCaching(IOperationInvoker innerOperationInvoker)
        {
            
this .innerOperationInvoker  =  innerOperationInvoker;
        }

        
#region  IOperationInvoker Members

        
public   object [] AllocateInputs()
        {
            
return   this .innerOperationInvoker.AllocateInputs();
        }

        
public   object  Invoke( object  instance,  object [] inputs,  out   object [] outputs)
        {
            
string  name  =  inputs[ 0 as   string ;
            
int  value;

            
if  ( this .identityCache.TryGetValue(name,  out  value))
            {
                outputs 
=   new   object [ 0 ];
                
return  value;
            }
            
else
            {
                value 
=  ( int ) this .innerOperationInvoker.Invoke(
                    instance, inputs, 
out  outputs);
                identityCache[name] 
=  value;
                
return  value;
            }
        }

        
public  IAsyncResult InvokeBegin( object  instance,  object [] inputs, 
            AsyncCallback callback, 
object  state)
        {
            
return   this .innerOperationInvoker.InvokeBegin(
                instance, inputs, callback, state);
        }

        
public   object  InvokeEnd( object  instance,  out   object [] outputs, IAsyncResult result)
        {
            
return   this .innerOperationInvoker.InvokeEnd(
                instance, 
out  outputs, result);
        }

        
public   bool  IsSynchronous
        {
            
get  {  return  innerOperationInvoker.IsSynchronous;  }
        }

        
#endregion
}

同时,可以定义一个申明标签来添加这个自定操作调用器到WCF的运行时行为中。该标签实现IOperationBehavior接口。


public   class  IdentityCacheAttribute: Attribute, IOperationBehavior
    {
        
#region  IOperationBehavior Members

        
public   void  AddBindingParameters(OperationDescription operationDescription,
            BindingParameterCollection bindingParameters)
        {
        }

        
public   void  ApplyClientBehavior(OperationDescription operationDescription,
            ClientOperation clientOperation)
        {
        }

        
public   void  ApplyDispatchBehavior(OperationDescription operationDescription,
            DispatchOperation dispatchOperation)
        {
            dispatchOperation.Invoker 
=   new  IdentityCaching(dispatchOperation.Invoker);
        }

        
public   void  Validate(OperationDescription operationDescription)
        {
        }

        
#endregion
    }

 

 

总结

WCF的体系结构运行进行大量的运行时自定义,其分布在调度、代理相交互的整个生命周期。除了执行参数检查、消息检查、消息格式化、操作选择、操作调用等自定义扩展外,还可以定义更高级的扩展来处理实例化、并发、寻址和安全等事项。这些更高级的扩展将在以后的文章中介绍。

代码下载

转载于:https://www.cnblogs.com/godtear/archive/2009/07/23/1529756.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值