WCF后续之旅(4):WCF Extension Point 概览
在本系列的每篇文章中,我多次提到WCF是一个极具可扩展性的分布是消息通信框架。为了让读者对WCF Extension有一个总体的的认识,在这里我会简单列举了我们经常使用的绝大部分的扩展点,以及通过这些扩展点能够解决实现项目开发中的那些问题。
有一点需要特别提醒的是:对WCF extensions的灵活应用依赖于你对channel layer和service mode dispatching system的深入理解。所以,如果你对channel layer不甚了解,可以参阅本系列的第一个部分(html" target=_blank>WCF是如何通过Binding进行通信的)和第二部分(如何对Channel Layer进行扩展——创建自定义Channel), 若是想了解更多关于dispatching system的细节,可以参考本系列的第三部分(WCF Service Mode Layer 的中枢—Dispatcher)。
现在,我们按照在上一篇文章的Dispatching的执行流程,来介绍dispatching system中可以用于对WCF进行扩展的对象,已经这个可扩展对象具体解决的问题和扩展的方式。为了利于读者理解这些可扩展对象具体被使用在Dispatching整个的生命周期的哪个阶段,我们在标注Step 1、Step 2…字样,读者可以在上一篇文章中查阅对应的步骤在执行怎样的功能
。
1 、自定义InstanceContextProvider(Step 5)
在WCF infrastructure中, InstanceContext是以一个很重要的概念。InstanceContext是什么呢?简言之,InstanceContext就是对service instance的封装(service instance wrapper),对于每一个service instance来讲,WCF都会通过一些contextual information对其进行包装。这些contextual information存在的目的在于让不同的request关联到对应的service instance上。对于不同的Instancing Mode(PerCall、PerSession和Singleton),我们往往具有不同的InstanceContext。而对于PerSession方式的instancing mode,InstanceContext显得尤为重要,原因很简单,我们必须保证来自同一个Session的request被分发到同一个service instance,不然很难维护其session的信息。
InstanceContext的获取通过InstanceContextProvider来实现。在WCF中所有的InstanceContextProvider实现了System.ServiceModel.Dispatcher.IInstanceContextProvider inte易做图ce。
public inte易做图ce IInstanceContextProvider
{
// Methods
InstanceContext GetExistingInstanceContext(Message message, IContextChannel channel);
void InitializeInstanceContext(InstanceContext instanceContext, Message message,IContextChannel channel);
bool IsIdle(InstanceContext instanceContext);
void NotifyIdle(InstanceContextIdleCallback callback, InstanceContext instanceContext);
}
- GetExistingInstanceContext:当message有ChannelDispather交付到EndpointDispatcher的时候,该方易做图被调用去试图获取一个已经存在的InstanceContext。比如:PerSession模式下,如果session已经开始,那个会返回绑定到当前session的InstanceContext,否则return null;对于Singleton模式,由于使用一个service instance来处理所有的request,所以一旦service instance被创建,后续的request都将返回同一个InstanceContext,否则return null;而对于PerCall来说,由于对于每个request来说,都需要创建一个新的service instance来处理,所以它永远是return null。
- InitializeInstanceContext:如何GetExistingInstanceContext返回null,将通过这个方法来创建和初始化一个新的InstanceContext.
- IsIdle:当所有的InstanceContext操作完成以后,该方易做图被调用,返回的bool类型的结果将用作是否对InstanceContext进行清理和回收的依据。如何你不希望对创建的InstanceContext进行回收,那么你可以将此方法返回为false。比如:Singleton和PerSession模式下就直接return false;而PerCall则return true。
- NotifyIdle:当对InstanceContext进行真正的清理和回收时,此方易做图被回调。
和3种instancing mode相匹配, WCF定义了3种InstanceContextProvider:
- System.ServiceModel.Dispatcher.PerCallInstanceContextProvider
- System.ServiceModel.Dispatcher.PerSessionInstanceContextProvider
- System.ServiceModel.Dispatcher.SingletonInstanceContextProvider
通过对InstanceContextProvider进行扩展,创建你自定义的InstanceContextProvider,你可以以你需要的方式关联request和service instance。比如:为了性能的提升,你可能试图通过一种对象池的机制实现对service instance的创建和提取,当需要使用到某个service instance的时候,先从对象池中获取该对象,如果不存在再从新创建对象。当service instance调用完毕,将其放入对象池中。这样避免了过于频繁的对象创建而引起对性能的影响。有兴趣的朋友不妨试着做一做。
注:当你自定义InstanceContextProvider的时候,一般继承base class:System.ServiceModel.Dispatcher.InstanceContextProviderBase而不是完全实现System.ServiceModel.Dispatcher.IInstanceContextProvider inte易做图ce。
2 、自定义MessageFilter(Step 6)
通过对dispatching system的介绍,我们了解到:当ChannelDispather通过ChannelListener创建的Channel接收到request message之后,自己不会对message进行处理,而是遍历自己的EndpointDispatcher集合属性,找到与request message相匹配的EndpointDispatcher。到底怎样的匹配规则会被采用呢?
具体实现是这样的:每个EndpointDispatcher都定义了两个特殊的属性:AddressFilter和ContractFilter,它们的类型继承了abstract class:System.ServiceModel.Dispatcher.MessageFilter。
public abstract class MessageFilter
{
// Methods
protected MessageFilter();
protected internal virtual IMessageFilterTable<FilterData> CreateFilterTable<FilterData>();
public abstract bool Match(Message message);
public abstract bool Match(MessageBuffer buffer);
}
MessageFilter定义了两个Match重载,所以子类实现该重载实现自定义的匹配规则。在具体实现的时候,会解析request message或者MessageBuffer (message 的memory buffer表示)(一般是message header),来判断该request是否和对应的EndpointDispatcher相互匹配。
WCF为我们提供了一下6类Message Filter:
- System.ServiceModel.Dispatcher.ActionMessageFilter:通过message Action header进行匹配。
- System.ServiceModel.Dispatcher.MatchAllMessageFilter:匹配所有的message,也就是直接返回true。
- System.ServiceModel.Dispatcher.EndpointAddressMessageFilter:根据message的To header 进行匹配。
- System.ServiceModel.Dispatcher.MatchNoneMessageFilter:不会和任何的message匹配,也就是直接返回false。
- System.ServiceModel.Dispatcher.PrefixEndpointAddressMessageFilter:和EndpointAddressMessageFilter相似,不过这次匹配的不是整个message的To header ,而是To header 的前缀。
- System.ServiceModel.Dispatcher.XPathMessageFilter:给予Xpath expression的匹配方式。
那么EndpointDispatcher的ContractFilter和AddressFilter采
补充:综合编程 , 其他综合 ,