这一篇中,我将和大家探讨一下如何扩展WCF service端的Dispatcher。因为可以讨论的方面是十分多的,所以在这里我只是列举了几个可能是比较常用的扩展点。至于关于Dispatcher其他的扩展,相信大家不难找出。
首先我们看一下Dispatcher的结构:
图是从MSDN上搞到的,有点大。
我们可以看到在ServiceHost下有两个Dispatcher:ChannelDispatcher、EndpointDispatcher。每个EndpointDispatcher中都有DispatchRuntime和DispatchOperation。DispatchRuntime将Message分发到对应的DispatchOperation,由后者来调用对应的方法来完成整个操作。接下来的实例中我们就从这两个类着手来进行扩展。不过首先我们要知道,这两个类处的层级是不同的。DispatchRuntime允许我们在Contract的范围内进行拦截和扩展,而DispatchOperation允许我们在Opertaion的范围内进行拦截和扩展。可能现在有点不清楚,待会看实例就会很明白了,其实对于我们来说就是获得的信息不一样而已。
首先我们先建一个WCF的应用程序,至于怎么建立我就不说了,这个也不是本文的主题。
接下来就干正事了。我们要清楚,扩展的方式就是将我们客制化的东西加入到WCF的运行时中。怎么加呢?对了,首先想到的应该就是Behavior。WCF中有各种各样的Behavior:Service Behavior、Endpoint Behavior、Operation Behavior等。至于你想选择什么Behavior,就根据你想把这扩展作用的范围来选择好了。这里我选择用Service Behavior。所以需要添加一个类来实现IServiceBehavior接口。
{
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher ch1 in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher end in ch1.Endpoints)
{
}
}
}
public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
}
}
现在要插入讲一下我的例子中待会要用到的两个接口:IDispatchMessageInspector和IParameterInspector。
IDispatchMessageInspector根据名字就可以看出主要用来拦截服务器端的消息的,定义如下:
{
// Methods
object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext);
void BeforeSendReply(ref Message reply, object correlationState);
}
IParameterInspector主要用来在方法调用时拦截参数的,定义如下:
{
// Methods
void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState);
object BeforeCall(string operationName, object[] inputs);
}
所以接下来我们就用这两个接口来分别实现在DispatchRuntime和DispatchOperation上的拦截,下面新加入两个类分别实现这两个接口:
{
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
}
public object BeforeCall(string operationName, object[] inputs)
{
Console.WriteLine(operationName + ": ");
foreach (object var in inputs)
{
Console.WriteLine("input: " + var.ToString());
}
return null;
}
}
public class MyMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
Trace.WriteLine(request);
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
Trace.WriteLine(reply);
}
}
然后把他们加入到Dispatch中,修改ApplyDispathBehavior方法:
{
foreach (ChannelDispatcher ch1 in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher end in ch1.Endpoints)
{
end.DispatchRuntime.MessageInspectors.Add(new MyMessageInspector());
foreach (DispatchOperation op in end.DispatchRuntime.Operations)
{
op.ParameterInspectors.Add(new MyParameterInspector());
}
}
}
}
最后,在你的Service类上打上标签就可以了:[MyBehavior]。
编译以后运行一下看看效果吧。
本文的例子并没有什么实质的使用场景,至于扩展Dispatcher可以对你的应用程序带来多大的好处,还希望你继续深入研究。当然,可扩展的点也不仅仅是MessageInspectors和ParameterInspectors。