WCF 扩展之我见: Service Model Layer

本系列索引,请见《开篇

本文将对 Service Model Layer 部分进行一个整体的介绍。如果需要查看该系列的其它文章,请点击 《WCF 扩展之我见: 开篇》。

The service model layer is responsible for pulling incoming messages out of the underlying channels, translating them into method invocations in application code, and sending the results back to the caller. Service model extensions modify or implement execution or communication behavior and features involving client or dispatcher functionality, custom behaviors, message and parameter interception, and other extensibility functionality.

-- <Extending ServiceHost and the Service Model Layer>

上面这段话摘自 MSDN,大概意思是说 service model layer 会负责把 Channel 中的消息转成对应用程序方法的调用,并把结果发送回调用方。service model 中提供的扩展可以用来修改消息的执行流程及一些特性。 而与此过程相关的编程点都可以作为 Service Model Layer 的一部分。

结合上一篇文章中介绍过的流程,service model layer 涉及到的大部分扩展点都位于 MessagePump 阶段,这其中就主要包含下面所列的扩展点(按照 MessagePump 出现的先后顺序排列):


InstanceContextProvider

InstanceContext 即(服务)实例的上下文,包含了当前 Instance 的相关信息,比如 Instance 相关的 Channel 信息、并发模式、事务信息、Timeout 时间等,主要用于当对服务的调用支持 Session 的时候,可以在不同的调用间共享上下文。而 InstanceContextProvider 则指明了 InstanceContext 是如何被创建的。在《ConcurrencyMode 与 InstanceContextMode.PerCall》中提到过 WCF 默认支持三种 InstanceContextProvider (PerCall, PerSession, Single),可以通过 InstanceContextMode 来进行切换。如果实现了自定义的 InstanceContextProvider,则所指定的 InstanceContextMode 将不再起作用。

MessageFilter

在上一篇中讲过,一个 ListenUri 可以包含一个或多个 endpoint。也就是说一个 ChannelDispatcher 会包含多个 EndpointDispatcher。因此,一个 message 要想抵达最终的 endpoint,必须要确定哪个 endpoint 才是目标。而这正是 MessageFilter 的作用。

通过自定义 MessageFilter 可以控制 EndpointDispatcher 的选择。


WCF 内置了8种 MessageFilter:

System.ServiceModel.Dispatcher.ActionMessageFilter 

System.ServiceModel.Dispatcher.EndpointAddressMessageFilter 

System.ServiceModel.Dispatcher.EndpointNameMessageFilter 

System.ServiceModel.Dispatcher.MatchAllMessageFilter 

System.ServiceModel.Dispatcher.MatchNoneMessageFilter 

System.ServiceModel.Dispatcher.PrefixEndpointAddressMessageFilter 

System.ServiceModel.Dispatcher.StrictAndMessageFilter 

System.ServiceModel.Dispatcher.XPathMessageFilter

MessageInspector

在 Message 被 EndpointDispatcher 进行指派前,以及返回 response 前,可以对 Message 进行任何操作,比如验证 Message,修改 Message,或者在该阶段对 Message 作一些其它操作。

MessageInspector 在 WCF 的客户端及服务端中有两种不同存在的形式:IClientMessageInspector 及 IDispatchMessageInspector。

    public interface IDispatchMessageInspector
    {    
        object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext);        
        void BeforeSendReply(ref Message reply, object correlationState);
    }

    public interface IClientMessageInspector
    {    
        object BeforeSendRequest(ref Message request, IClientChannel channel);        
        void AfterReceiveReply(ref Message reply, object correlationState);
    }


InstanceProvider

用于提供 Instance 的创建和释放,下面是 InstanceProvider 的类型定义:

    public interface IInstanceProvider
    {    
        object GetInstance(InstanceContext instanceContext);        
        object GetInstance(InstanceContext instanceContext, Message message);        
        void ReleaseInstance(InstanceContext instanceContext, object instance);
    }


使用 InstanceProvider 就可以控制一个服务实例是如何被创建的了,由其是当实例化一个服务实例时需要一些特殊的操作,比如使用了 IoC 的情况。


ICallContextInitializer

当一个服务实例创建后,就会由一个线程进行执行,通过 CallCOntextInitializer 可以对该线程进行初始化,设置线程的本地存储(TLS)

    public interface ICallContextInitializer
    {    
        object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message);        
        void AfterInvoke(object correlationState);
    }


MessageFormatter

Message 是以消息的形态存在的,无法被直接解释成 CLR 中对应的方法及参数,因此需要有一个反序列化的方法把 Message 转换为实际调用的参数,或把返回值转换成 Message。而实现这个功能的便是 MessageFormatter。

与 MessageInpsector 类似,在客户端及服务端之间存在两种不同的形式:IClientMessageFormatter 及 IDispatchMessageFormatter

    public interface IDispatchMessageFormatter
    {    
        void DeserializeRequest(Message message, object[] parameters);        
        Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result);
    }
    
    public interface IClientMessageFormatter
    {   
         Message SerializeRequest(MessageVersion messageVersion, object[] parameters);        
         object DeserializeReply(Message message, object[] parameters);
    }


ParameterInspector

与 MessageInspector 不同的是,MessageInpsector 操作的是 Message,而 ParameterInspector 操作的则是 CLR 的类型。通过使用 ParameterInspector,能够在对应的方法被调用前、调用后对输入、输出及返回值进行操作。

    public interface IParameterInspector
    {    
        object BeforeCall(string operationName, object[] inputs);        
        void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState);
    }


OperationInvoker

这是方法被调用前的最后一步,通过 OperationInvoker 就会调用真正的 Method 对消息进行处理。通过它的这个能力,可以对方法调用进行缓存,这样下次调用同一个 Method 时,则可以直接返回上次的调用结果。

    public interface IOperationInvoker
    {   
        bool IsSynchronous { get; } 
        object[] AllocateInputs();         
        object Invoke(object instance, object[] inputs, out object[] outputs); 
        IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state); 
        object InvokeEnd(object instance, out object[] outputs, IAsyncResult result);
    }


IErrorHandler

在 WCF 的调用期间,各个环节都有可能会抛出异常,如果我们希望对异常有一个统一的处理方式,则可以通过 IErrorHandler 来实现自己的异常处理,比如在返回的 Message 中加入一些错误信息。

    public interface IErrorHandler
    {    
        void ProvideFault(Exception error, MessageVersion version, ref Message fault);        
        bool HandleError(Exception error);
    }


IExtensibleObject<T> 和 IExtension<T>

通过结合使用这两个接口,可以方便的为一个对象添加上新的属性或行为。WCF 中有四类对象支持 IExtensibleObject: ServiceHostBase,InstanceContext,OperationContext,IContextChannel。所以如果想对这四类对象进行扩展,可以简单的使用 IExtension 的方式进行扩展。


Behaviors

从上篇文章中,可以看出在最初服务启动的时候,会先对 Description 进行初始化,然后在设置服务运行环境的时候又会去遍历这些 Description 来对环境进行设置。因此,可以认为 Description 即是对宿主环境的描述,所有希望宿主环境具备的额外功能都可以通过 Description 进行描述。

而 Behaviors 属于 Description 中的重要部分,通过使用 Behaviors 就可以把基于上述扩展点的自定义扩展添加到宿主环境中。


Behaviors 主要分为四类: ServiceBehavior, ContractBehavior, EndpointBehavior 及 OperationBehavior。

文章索引

[隐 藏]

本站采用知识共享署名 3.0 中国大陆许可协议进行许可。 ©2014 Charley Box | About Site | 浙ICP备13014059号