Reflection

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

这一篇中,我将和大家探讨一下如何扩展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 class MyBehavior : Attribute, 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)
        
{
        }

    }
在ApplyDispathBehavior方法中,通过两个循环我们就获得了EndpointDispatcher对象了,接下来就可以用它来访问到DispatchRuntime和DispatchOperation了。
现在要插入讲一下我的例子中待会要用到的两个接口:IDispatchMessageInspectorIParameterInspector
IDispatchMessageInspector根据名字就可以看出主要用来拦截服务器端的消息的,定义如下:
public interface IDispatchMessageInspector
{
    
// Methods
    object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext);
    
void BeforeSendReply(ref Message reply, object correlationState);
}



IParameterInspector主要用来在方法调用时拦截参数的,定义如下:
public interface IParameterInspector
{
    
// Methods
    void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState);
    
object BeforeCall(string operationName, object[] inputs);
}


 

所以接下来我们就用这两个接口来分别实现在DispatchRuntime和DispatchOperation上的拦截,下面新加入两个类分别实现这两个接口:
    public class MyParameterInspector : IParameterInspector
    
{

        
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方法:
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
    
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。
posted on 2008-05-21 15:45  Reflection  阅读(712)  评论(0编辑  收藏  举报