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

1.       与WCF定制行为相关的namespace
用来扩展WCF扩展行为的namespace主要包括2个:
a. System.ServiceModel.Disptcher:
该namespace主要用来用来定制行为,他们可以用来扩展WCF的服务模型。
b. System.ServiceModel.Channels:
该namespace用来定义定制绑定元素,它们可以扩展WCF的信道层。

2.       定制行为的分类

3.       实现定制行为的步骤
实现定制行为一般分为3步:
1. 声明扩展:
     声明所要提供的行为的类型, 例如是工作在客户端中以将发送的数据序列化到消息里,还是工作在服务中以管理服务类型的实例等等
2.附加扩展:
    第2步需要将所定制的extension附加到相应的操作,终结点或者服务端行为上。
例如对于客户端来说:

a.       当他是操作相关(Operation)的时候,则将该定制行为附加到操作上,即实现System.ServiceModel.Description.IOperationBehavior接口。

b.      当他是终结点(Endppoint)相关的时候 ,则将该定制行为附加到终结点上,即实现System.ServiceModel.Description.IEndpointBehavior接口。

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

对于附加到操作上的扩展行为,只能采用programatically的方式告知,而对于附加到终结点上的扩张行为,告知的方式有2种,分别为programatically和administratively:
     a.  使用代码告知(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());
    }

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

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

step1: 声明

通过实现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

}

step2: 附加

通过实现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

}

Step3: 告知(inform)

告知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.配置告知
 1. 定义一个extension(需要指定extension name和extension type)

2. 选定刚才的extension

3.       将该extension应用到EndpointBehavior

实例讲解2-定制一个服务端错误处理器来扩展服务端错误处理机制
 1 扩展行为声明和附加

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

}

2. 告知
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();

}

}

运行结果screenshot:

客户端:

服务端:

有关Extending WCF with custom behaviors的详细文档,请参阅:

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

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

转载于:https://www.cnblogs.com/Winston/archive/2009/02/10/1387260.html

如何通过扩展WCF来定制和扩展WCF行为相关推荐

  1. 通过WCF Extension定制扩展WCF行为

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

  2. VC浏览器的定制与扩展

    前言 由于本人在开发中经常要在程序中嵌入浏览器,为了符合自己的需求经常要对浏览器进行扩展和定制, 解决这些问题需在网上找资料和学习的过程,我想可能很多开发者或许会遇到同样的问题,特写此文,以供大家参考 ...

  3. linux扩展两个桌面,经验分享:九大GNOME Shell扩展助您定制桌面Linux

    原标题:经验分享:九大GNOME Shell扩展助您定制桌面Linux 每位用户在首次设置新计算机时,都会进行有针对性的自定义--包括切换桌面环境.安装终端shell.选择自己喜欢的浏览器或者更改壁纸 ...

  4. SAP ABAP CO核心扩展-为企业定制ZCKM3N物料价格分析增强(CKM3 CKM3N CKM8N)

    SAP ABAP CO核心扩展-为企业定制ZCKM3N物料价格分析增强(CKM3 CKM3N CKM8N) 引言: 这篇文章,将为大家讲述物料价格分析扩展增强(ZCKM3N)的方法和原理,并基于CKM ...

  5. 扩展bash_Bash中的参数扩展简介

    扩展bash 在Bash中,存储值的实体称为参数. 它们的值可以是具有常规语法的字符串或数组,也可以是整数或关联数组(当使用内置声明的特殊属性设置时). 参数共有三种:位置参数,特殊参数和变量. 为了 ...

  6. php扩展 静态库,编译PHP扩展的方法

    [相关学习推荐:php编程(视频)] 构建PHP扩展 你已经知道如何去编译PHP本身,下一步我们将编译外部扩展.我们将讨论扩展的构建过程和可用的编译选项. 载入共享扩展 在前一个章节你已经知道,PHP ...

  7. 【Groovy】Groovy 扩展方法 ( 实例扩展方法配置 | 扩展方法示例 | 编译实例扩展类 | 打包实例扩展类字节码到 jar 包中 | 测试使用 Thread 实例扩展方法 )

    文章目录 一.扩展方法示例 二.实例扩展方法配置 三.编译实例扩展类 四.打包静态扩展类字节码到 jar 包中 五.测试使用 Thread 实例扩展方法 一.扩展方法示例 为 Thread 扩展 he ...

  8. 【Groovy】Groovy 扩展方法 ( 静态扩展方法配置 | 扩展方法示例 | 编译静态扩展类 | 打包静态扩展类字节码到 jar 包中 | 测试使用 Thread 静态扩展类 )

    文章目录 一.扩展方法示例 二.静态扩展方法配置 三.编译静态扩展类 四.打包静态扩展类字节码到 jar 包中 五.测试使用 Thread 静态扩展类 一.扩展方法示例 为 Thread 扩展 hel ...

  9. php扩展的xdebug,安装php扩展:Xdebug

    之前一直没有使用xdebug,程序依然跑的飞快.但是对于底层怎么解析.处理写的这些php程序呢?不知道.xdebug或许可以对你有帮助. xdebug 是 php的一个扩展库,需要专门安装才可以使用. ...

最新文章

  1. javascript常用工具类封装
  2. 主机电源全是黑线怎么短接_汽车胎压监测即将成为强制标准,听听老司机怎么说...
  3. tensorflow tf.nn.max_pool_with_argmax返回最大池化对应索引值
  4. 【c#】Form调用百度地图api攻略及常见问题
  5. 树网的核 Vijos1362 NOIP2007 树结构 直径 暴搜
  6. 中怎样载入选区_【平面设计教学】Photoshop基本教学-第3章 选区与填色
  7. Git命令集十三——快照操作
  8. buck变换器设计matlab_一种用于Boost PFC变换器的改进关断时间控制策略
  9. python训练营朋友圈留言_用Python发一个高逼格的朋友圈【附代码】
  10. ERROR ITMS-90022,90023,问题已解决
  11. ie不加载jre_国内银行为兼容XP/IE6 竟然篡改IE安全协议把所有用户拖下水
  12. 还没买到票?快试试这个Python开源工具,支持多任务抢票
  13. SQL2005学习(三十二),Group by
  14. 【Alpha】Daily Scrum Meeting——Day2
  15. Android总结篇系列:Activity中几个主要函数详解
  16. MAC地址厂商信息查询
  17. spss——主成分分析详解
  18. ​自动驾驶测试与验证的挑战
  19. linux uwf开放80端口,SELinux - osc_a3uwfsx7的个人空间 - OSCHINA - 中文开源技术交流社区...
  20. 吉林省教育学院学报杂志社吉林省教育学院学报编辑部2022年第9期目录

热门文章

  1. 用C#语言实现记事本(Windows程序设计作业3)
  2. 网络维护优化是做什么的(网络维护措施)
  3. lazada API 按关键字搜索商品
  4. Oracle tnsping 03505,oracle客户端tnsping,提醒:TNS-03505: 无法解析名称
  5. qt 静态 mysql_qt中如何使用mysql 以及静态编译qt中如何加上mysql(1)
  6. Python字符串使用详解
  7. matlab hough算法车牌识别,一种基于数学形态学和Hough变换的车牌图像检测及定位算法-汽车电子-与非网...
  8. HDU4856:Tunnels (BFS 状压dp)
  9. HDU4856 Tunnels 状压DP
  10. 【Home键的监听】