功能介绍

当我们需要扩展WCF的功能,或者需要实现某些特定的功能,我们必须应用WCF的扩展定制功能(WCF extension),WCF framework提供了丰富的可扩展性,其提供的可扩展接口如下所示:

WCF定制行为相关的namespace主要包括2个:

  • System.ServiceModel.Disptcher: 该namespace主要用来用来定制行为,他们可以用来扩展WCF的服务模型。
  • System.ServiceModel.Channels: 该namespace用来定义定制绑定元素,它们可以扩展WCF的信道层。

实现定制行为的步骤 实现定制行为一般分为3步:

1. 声明扩展: 声明所要提供的行为的类型, 例如是工作在客户端中以将发送的数据序列化到消息里,还是工作在服务中以管理服务类型的实例等等。

2. 附加扩展: 第2步需要将所定制的extension附加到相应的操作,终结点或者服务端行为上。

例如对于客户端来说: 当他是操作相关(Operation)的时候,则将该定制行为附加到操作上,即实现System.ServiceModel.Description.IOperationBehavior接口。 当他是终结点(Endppoint)相关的时候 ,则将该定制行为附加到终结点上,即实现System.ServiceModel.Description.IEndpointBehavior接口。

3. 告知(inform): 告知的作用就是将那些自己定义的扩展行为告知客户端运行时组件(ClientRunTime)或者服务端调度器(EndpointDispatcher)。

对于附加到操作上的扩展行为,只能采用programatically的方式告知,而对于附加到终结点上的扩张行为,告知的方式有2种,分别为programatically和administratively:

  • 使用代码告知(programmatically)

以客户端为例: 当把该定制行为附加到operation上时,即实现了IOperationBehavior时候,其告知行为应该为operation-level的:

public MyServiceClient()
    {
         foreach (System.ServiceModel.Description.OperationDescription operation in base.Endpoint.Contract.Operations)
            {
                operation.Behaviors.Add(new MyParameterInspector());
            }
      
      //  base.Endpoint.Contract.Operations[0].Behaviors.Add(new WCFClient.MyParameterInspector());
    }

当把该定制行为 附加到endpoint上时,其告知行为应该为endpoint-level的。

 public MyServiceClient()
    {
       base.Endpoint.Behaviors.Add(new MyMessageInspector());
    }
  • 使用配置告知(administratively)

为了通过配置告知WCF服务模型定制行为的存在,必须提供一个从抽象基类System.ServiceModel.Configuration.BehaviorExtensionElement继承的类。

实例讲解

实例1. 定制一个客户端消息检查器来扩展客户端Endpoint的行为

声明:通过实现System.ServiceModel.Disptcher.IClientMessageInspector接口来声明一个消息检查的扩展行为

public class MyMessageInspector : System.ServiceModel.Dispatcher.IClientMessageInspector
    {
        #region IClientMessageInspector implementation
        public void AfterReceiveReply(
            ref System.ServiceModel.Channels.Message reply,
            object correlationState)
        {
            Console.WriteLine("--------------------");
            Console.WriteLine("AfterReceiveReply Behavior extension");
            Console.WriteLine("--------------------");
        }
 
        public object BeforeSendRequest(
            ref System.ServiceModel.Channels.Message request,
            System.ServiceModel.IClientChannel channel)
        {
            Console.WriteLine("--------------------");
            Console.WriteLine("Before Sending Request Behavior extension");
            Console.WriteLine("--------------------");
            return null;
        }
        #endregion 
 
 
    }

附加:通过实现System.ServiceModel.Discription.IEndpointBehavior接口来完成该扩张行为在客户段的附加

public class MyMessageInspector : System.ServiceModel.Dispatcher.IClientMessageInspector,
        System.ServiceModel.Description.IEndpointBehavior
{
//声明部分:
        #region IClientMessageInspector implementation
        public void AfterReceiveReply(
            ref System.ServiceModel.Channels.Message reply,
            object correlationState)
        {
        }
 
        public object BeforeSendRequest(
            ref System.ServiceModel.Channels.Message request,
            System.ServiceModel.IClientChannel channel)
        {
            return null;
        }
        #endregion 
 
//附加部分:
        #region Implementation for IEndpointBehaviour
        public void AddBindingParameters(ServiceEndpoint serviceendpoint,
            BindingParameterCollection parameters
            )
        {
            //no implementation;
        }
 
        public void ApplyClientBehavior(
            ServiceEndpoint serviceendpint,
            ClientRuntime behavior)
        {
            behavior.MessageInspectors.Add(this);
        }
 
        public void ApplyDispatchBehavior(
            ServiceEndpoint serviceendpoint,
            EndpointDispatcher dispatcher)
        {
 
        }
 
        public void Validate(ServiceEndpoint serviceendpoint)
        {
            //no implemetentation;
        }
        #endregion 
    }

告知:告知WCF服务模型该行为的存在,有2种方式:programmatically和administratively. 为了实现服务与配置的低耦合,administratively是推荐的方式。

注意:通过培植方式将定制行为告知 WCF,必须提供一个从抽象基类System.ServiceModel.Configuration.BehaviorExtensionElement继承的类。

1. 重写基类

public class MyBehaviorExtensionelement : System.ServiceModel.Configuration.BehaviorExtensionElement
    {
 
        public override Type BehaviorType
        {
            get { return typeof(MyMessageInspector); }
        }
 
        protected override object CreateBehavior()
        {
            return new MyMessageInspector();
        }
}

2. 配置告知  

定义一个extension(需要指定extension name和extension type)

选定刚才的extension

将该extension应用到EndpointBehavior

实例2. 定制一个服务端错误处理器来扩展服务端错误处理机制

扩展行为声明和附加

public class MyErrorHandler : IErrorHandler,IServiceBehavior
{
//声明扩展部分
        public bool HandleError(Exception error)
        {
            Console.WriteLine("The exception information will be logged:");
            Console.WriteLine(error.Message);
            return true;
        }
 
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
           
        }
//附加扩展部分
        #region Implementation for IServiceBehaviour
        public void AddBindingParameters(ServiceDescription descip,
            ServiceHostBase host,
            Collection<ServiceEndpoint> endpoints,
            BindingParameterCollection parameters
            )
        {
            //no implementation;
        }
 
        public void ApplyDispatchBehavior(ServiceDescription desciption,
            ServiceHostBase host)
        {
            IErrorHandler hanlder = new MyErrorHandler();
            foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(hanlder);
            }
        }
 
        public void Validate(ServiceDescription description,
            ServiceHostBase host)
       {
            //no implemetentation;
        }
        #endregion 
 
    }

 告知

public class MyErrorBehaviorExtensionElement : System.ServiceModel.Configuration.BehaviorExtensionElement
{
        public override Type BehaviorType
        {
            get { return typeof(MyErrorHandler); }
        }
        protected override object CreateBehavior()
        {
            return new MyErrorHandler();
        }
}

客户端consume WCF service snippet:

namespace WCFClient
{
    class Program
    {
        public class ClientWrapper:IDisposable
        {
            private MyServiceClient _proxy;
            public ClientWrapper()
            {
                _proxy = new MyServiceClient();
            }
 
            public void MyMethod(bool ThrowExporNot)
            {
                try
                {
                    _proxy.MyMethod(ThrowExporNot);
                }
                catch (System.ServiceModel.FaultException<MyCustomException> ex)
                {
                    Console.WriteLine(ex.Reason);
                   
                }
            }
 
            public void Dispose()
            {
                _proxy.Close();
            }
            
        }
 
        static void Main(string[] args)
        {
            ClientWrapper wrap = new ClientWrapper();
            wrap.MyMethod(true);          
            Console.Read();
        }
            
    }
}

服务端self-hosted WCF service snippet:

class Program
    {
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(MyService));
          
            Console.WriteLine("The service is online...");
            Console.WriteLine("Press <ENTER> to exit");
            host.Open();
            Console.Read();
        }
}

运行结果

客户端:

服务端:

参考文档

更多Extending WCF with custom behaviors的详细文档,请参阅:

http://msdn.microsoft.com/zh-cn/magazine/cc163302.aspx(中文)

http://msdn.microsoft.com/en-us/magazine/cc163302.aspx(英文)




希望以上文章对您有所帮助

Winston

 

 

 

 

posted on 2013-05-09 09:59  微软互联网开发支持  阅读(1543)  评论(0编辑  收藏  举报