WCF自定义扩展,以实现aop!
使用自定义行为扩展 WCF
代码下载位置: ServiceStation2007_12.exe (165 KB)
Browse the Code Online
Figure 4 调度程序/代理扩展摘要| 阶段 | 侦听器接口 | 说明 |
|---|---|---|
| 参数检查 | IParameterInspector | 在调用前后调用,以检查和修改参数值。 |
| 消息格式化 | IDispatchMessageFormatter IClientFormatter | 调用以执行序列化和反序列化。 |
| 消息检查 | IDispatchMessageInspector IClientMessageInspector | 发送前或收到后调用,以检查和替换消息内容。 |
| 操作选择 | IDispatchOperationSelector IClientOperationSelector | 调用以选择要为给定的消息调用的操作。 |
| 操作调用程序 | IOperationInvoker | 调用以调用操作 |
[ServiceContract] public interface IZipCodeService {
[OperationContract]
string Lookup(string zipcode);
}
Figure 5 邮政编码验证参数检查器public class ZipCodeInspector : IParameterInspector { int zipCodeParamIndex; string zipCodeFormat = @"\d{5}-\d{4}"; public ZipCodeInspector() : this(0) { } public ZipCodeInspector(int zipCodeParamIndex) { this.zipCodeParamIndex = zipCodeParamIndex; } ... // AfterCall is empty public object BeforeCall(string operationName, object[] inputs) { string zipCodeParam = inputs[this.zipCodeParamIndex] as string; if (!Regex.IsMatch( zipCodeParam, this.zipCodeFormat, RegexOptions.None)) throw new FaultException( "Invalid zip code format. Required format: #####-####"); return null; } }
Figure 6 控制台跟踪消息检查器public class ConsoleMessageTracer : IDispatchMessageInspector, IClientMessageInspector { private Message TraceMessage(MessageBuffer buffer) { Message msg = buffer.CreateMessage(); Console.WriteLine("\n{0}\n", msg); return buffer.CreateMessage(); } public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { request = TraceMessage(request.CreateBufferedCopy(int.MaxValue)); return null; } public void BeforeSendReply(ref Message reply, object correlationState) { reply = TraceMessage(reply.CreateBufferedCopy(int.MaxValue)); } public void AfterReceiveReply(ref Message reply, object correlationState) { reply = TraceMessage(reply.CreateBufferedCopy(int.MaxValue)); } public object BeforeSendRequest(ref Message request, IClientChannel channel) { request = TraceMessage(request.CreateBufferedCopy(int.MaxValue)); return null; } }
Figure 7 邮政编码缓存操作调用程序public class ZipCodeCacher : IOperationInvoker { IOperationInvoker innerOperationInvoker; Dictionary<string, string> zipCodeCache = new Dictionary<string, string>(); public ZipCodeCacher(IOperationInvoker innerOperationInvoker) { this.innerOperationInvoker = innerOperationInvoker; } public object Invoke(object instance, object[] inputs, out object[] outputs) { string zipcode = inputs[0] as string; string value; if (this.zipCodeCache.TryGetValue(zipcode, out value)) { outputs = new object[0]; return value; } else { value = (string)this.innerOperationInvoker.Invoke( instance, inputs, out outputs); zipCodeCache[zipcode] = value; return value; } } ... // remaining methods elided // they simply delegate to innerOperationInvoker }
Figure 9 行为接口方法| 方法 | 说明 |
|---|---|
| 验证 | 仅在构建运行时前调用 — 允许您对服务说明执行自定义验证。 |
| AddBindingParameters | 在构建运行时的第一步时,且在构造底层通道前调用 — 允许添加参数,以影响底层通道堆栈。 |
| ApplyClientBehavior | 允许行为插入代理(客户端)扩展。请注意,IServiceBehavior 中不存在该方法。 |
| ApplyDispatchBehavior | 允许行为插入调度程序扩展。 |
Figure 8 行为类型| 作用域 | 接口 | 潜在影响 | |||
| 服务 | 终结点 | 约定 | 操作 | ||
| 服务 | IServiceBehavior | ✗ | ✗ | ✗ | ✗ |
| 终结点 | IEndpointBehavior | ✗ | ✗ | ✗ | |
| 约定 | IContractBehavior | ✗ | ✗ | ||
| 操作 | IOperationBehavior | ✗ |
Figure 10 操作行为示例public class ZipCodeValidation : Attribute, IOperationBehavior { public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { ZipCodeInspector zipCodeInspector = new ZipCodeInspector(); clientOperation.ParameterInspectors.Add(zipCodeInspector); } public void ApplyDispatchBehavior( OperationDescription operationDescription, DispatchOperation dispatchOperation) { ZipCodeInspector zipCodeInspector = new ZipCodeInspector(); dispatchOperation.ParameterInspectors.Add(zipCodeInspector); } ... // remaining methods empty } public class ZipCodeCaching : Attribute, IOperationBehavior { public void ApplyDispatchBehavior( OperationDescription operationDescription, DispatchOperation dispatchOperation) { dispatchOperation.Invoker = new ZipCodeCacher(dispatchOperation.Invoker); } ... // remaining methods empty }
Figure 11 终结点和服务行为示例public class ConsoleMessageTracing : Attribute, IEndpointBehavior, IServiceBehavior { void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new ConsoleMessageTracer()); } void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { endpointDispatcher.DispatchRuntime.MessageInspectors.Add( new ConsoleMessageTracer()); } ... // remaining methods empty void IServiceBehavior.ApplyDispatchBehavior( ServiceDescription desc, ServiceHostBase host) { foreach ( ChannelDispatcher cDispatcher in host.ChannelDispatchers) foreach (EndpointDispatcher eDispatcher in cDispatcher.Endpoints) eDispatcher.DispatchRuntime.MessageInspectors.Add( new ConsoleMessageTracer()); } ... // remaining methods empty }
ServiceHost host = new ServiceHost(typeof(ZipCodeService)); host.Description.Behaviors.Add(new ConsoleMessageTracing());
ServiceHost host = new ServiceHost(typeof(ZipCodeService)); foreach (ServiceEndpoint se in host.Description.Endpoints) se.Behaviors.Add(new ConsoleMessageTracing());
ZipCodeServiceClient client = new ZipCodeServiceClient(); client.ChannelFactory.Endpoint.Behaviors.Add( new ConsoleMessageTracing());
[ServiceContract] public interface IZipCodeService { [ZipCodeCaching] [ZipCodeValidation] [OperationContract] string Lookup(string zipcode); } [ConsoleMessageTracing] public class ZipCodeService : IZipCodeService { ... }
public class ConsoleMessageTracingElement : BehaviorExtensionElement { public override Type BehaviorType { get { return typeof(ConsoleMessageTracing); } } protected override object CreateBehavior() { return new ConsoleMessageTracing(); } }
Figure 13 配置行为<configuration> <system.serviceModel> <services> <service name="ZipCodeServiceLibrary.ZipCodeService" behaviorConfiguration="Default"> <endpoint binding="basicHttpBinding" contract="ZipCodeServiceLibrary.IZipCodeService"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="Default"> <serviceMetadata httpGetEnabled="true"/> <consoleMessageTracing/> </behavior> </serviceBehaviors> </behaviors> <extensions> <behaviorExtensions> <add name="consoleMessageTracing" type="Extensions. ConsoleMessageTracingElement, Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> </behaviorExtensions> </extensions> </system.serviceModel> </configuration>
Figure 14 行为配置选项| 行为类型 | 配置选项 | ||
| 属性 | 配置 | 显式 | |
| 服务 | ✗ | ✗ | ✗ |
| 终结点 | ✗ | ✗ | |
| 约定 | ✗ | ✗ | |
| 操作 | ✗ | ✗ |
public class NoBasicEndpointValidator : Attribute, IServiceBehavior { #region IServiceBehavior Members public void Validate(ServiceDescription desc, ServiceHostBase host) { foreach (ServiceEndpoint se in desc.Endpoints) if (se.Binding.Name.Equals("BasicHttpBinding")) throw new FaultException( "BasicHttpBinding is not allowed"); } ... //remaining methods empty }
WCF自定义扩展,以实现aop!的更多相关文章
- SharePoint 2013 自定义扩展菜单
在对SharePoint进行开发或者功能扩展的时候,经常需要对一些默认的菜单进行扩展,以使我们开发的东西更适合SharePoint本身的样式.SharePoint的各种功能菜单,像网站设置.Ribbo ...
- SharePoint 2013 自定义扩展菜单(二)
接博文<SharePoint 2013 自定义扩展菜单>,多加了几个例子,方便大家理解. 例七 列表设置菜单扩展(listedit.aspx) 扩展效果 XML描述 <CustomA ...
- Jquery自定义扩展方法(二)--HTML日历控件
一.概述 研究了上节的Jquery自定义扩展方法,自己一直想做用jquery写一个小的插件,工作中也用到了用JQuery的日历插件,自己琢磨着去造个轮子--HTML5手机网页日历控件,废话不多说,先看 ...
- Silverlight实例教程 - 自定义扩展Validation类,验证框架的总结和建议(转载)
Silverlight 4 Validation验证实例系列 Silverlight实例教程 - Validation数据验证开篇 Silverlight实例教程 - Validation数据验证基础 ...
- jQuery 自定义扩展,与$冲突处理
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- SparkContext自定义扩展textFiles,支持从多个目录中输入文本文件
需求 SparkContext自定义扩展textFiles,支持从多个目录中输入文本文件 扩展 class SparkContext(pyspark.SparkContext): def ...
- 基于 HtmlHelper 的自定义扩展Container
基于 HtmlHelper 的自定义扩展Container Intro 基于 asp.net mvc 的权限控制系统的一部分,适用于对UI层数据呈现的控制,基于 HtmlHelper 的扩展组件 Co ...
- 第十三节:HttpHander扩展及应用(自定义扩展名、图片防盗链)
一. 自定义扩展名 1. 前言 凡是实现了IHttpHandler接口的类均为Handler类,HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...
- Asp.Net Mvc 自定义扩展
目录: 自定义模型IModelBinder 自定义模型验证 自定义视图引擎 自定义Html辅助方法 自定义Razor辅助方法 自定义Ajax辅助方法 自定义控制器扩展 自定义过滤器 自定义Action ...
随机推荐
- POJ 1258 Agri-Net(最小生成树 Prim+Kruskal)
题目链接: 传送门 Agri-Net Time Limit: 1000MS Memory Limit: 10000K Description Farmer John has been elec ...
- HDU 4768 Flyer(二分)
题目链接: 传送门 Flyer Time Limit: 1000MS Memory Limit: 32768 K Description The new semester begins! Di ...
- HTML之:让网页中的<a>标签属性统一设置-如‘新窗口打开’
在开发过程中,我们往往想在页面中,给<a>设置一个统一的默认格式,例如我们想让链接:“在新窗口打开”,我们就可以使用<base>标签 在网页中添加这段代码: <head& ...
- Linux Shell 从入门到删除根目录跑路指南
1.变量为空导致误删文件base_path=/usr/sbintmp_file=`cmd_invalid`# rm -rf $base_path/$tmp_file这种情况下如果 cmd 执行出错或者 ...
- Python基本数据类型之dict
一.创建字典: d = { "name": "morra", #字典是无序的 "age": 99, "gender": ...
- >>> FilterDispatcher <<< is deprecated! Please use the new filters!
在struts2.3.20下,web.xml中使用 会出现*********************************************************************** ...
- ionic的scroll的使用出现的问题
今天再写ionic的时候发现了一个问题,在使用ui-view的时候引用ion-scroll指令的时候初次加载的时候能能实现拖拽滚动,只能实现滚动鼠标滚轴滚动,然后各种调试,各种比较,终于发现原来是路由 ...
- BZOJ4446: [Scoi2015]小凸玩密室
用ui,j表示走完i的子树后走到i的深度为j的祖先的兄弟的最小代价: 用vi,j表示走完i的子树后走到i的深度为j的祖先的最小代价,用u算出v. 枚举起点,计算答案. #include<bits ...
- BZOJ3226: [Sdoi2008]校门外的区间
感觉很有趣的题呢. 每个点拆成两个,线段树维护. 不过这题难点其实在输入输出. #include<bits/stdc++.h> #define N (1<<17) #defin ...
- 匿名函数:Lambda表达式和匿名方法
匿名函数一个"内联"语句或表达式,可在需要委托类型的任何地方使用.可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数. 共有两种匿名函数: Lamb ...