在WCF中,当我们在调用服务端的方法时,一般有两点需要考虑:1、捕获服务端的异常信息,记录日志;2、及时关闭会话信道,当调用超时或调用失败时及时中断会话信道。我们一般会像下面这样处理(以CalculatorService为例):

using (ChannelFactory<ICalculatorService> channelFactory = new ChannelFactory<ICalculatorService>("CalculatorService"))
{
ICalculatorService proxy = channelFactory.CreateChannel();
var commObj = proxy as ICommunicationObject;
try
{
Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, proxy.Add(1, 2));
commObj.Close();
}
catch (CommunicationException)
{
commObj.Abort();
}
catch (TimeoutException)
{
commObj.Abort();
}
catch (Exception)
{
//TODO:记录异常到日志
commObj.Abort();
throw;
}
}

以上这种处理方式完全可以满足我们的需要,但存在一个问题,每次调用服务端的方法时都需要手工加上这些异常捕获代码,如果服务有很多方法时,这样势必会存在大量功能重复的代码,可复用性很差。我们可以借鉴一下AOP的思想,具体来说就是对服务端方法调用进行拦截。对于.Net应用来说,自定义RealProxy是实现方法调用拦截最简单的一种方式。下面是一个自定义RealProxy的例子:

public class CalculatorServiceRealProxy : RealProxy
{
public CalculatorServiceRealProxy():base(typeof(ICalculatorService)){}
public override IMessage Invoke(IMessage msg)
{
IMethodReturnMessage methodReturn = null;
IMethodCallMessage methodCall = (IMethodCallMessage)msg;
var client = new ChannelFactory<ICalculatorService>("CalculatorService");
var channel = client.CreateChannel();
try
{
object[] copiedArgs = Array.CreateInstance(typeof(object), methodCall.Args.Length) as object[];
methodCall.Args.CopyTo(copiedArgs, 0);
object returnValue = methodCall.MethodBase.Invoke(channel, copiedArgs);
methodReturn = new ReturnMessage(returnValue,
copiedArgs,
copiedArgs.Length,
methodCall.LogicalCallContext,
methodCall);
//TODO:Write log
}
catch (Exception ex)
{
var exception = ex;
if (ex.InnerException != null)
exception = ex.InnerException;
methodReturn = new ReturnMessage(exception, methodCall);
}
finally
{
var commObj = channel as ICommunicationObject;
if (commObj != null)
{
try
{
commObj.Close();
}
catch (CommunicationException)
{
commObj.Abort();
}
catch (TimeoutException)
{
commObj.Abort();
}
catch (Exception)
{
commObj.Abort();
//TODO:Logging exception
throw;
}
}
}
return methodReturn;
}
}

方法调用:

static void Main(string[] args)
{ ICalculatorService proxy = (ICalculatorService)new CalculatorServiceRealProxy().GetTransparentProxy(); Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, proxy.Add(1, 2));
Console.WriteLine("x - y = {2} when x = {0} and y = {1}", 1, 2, proxy.Subtract(1, 2));
Console.WriteLine("x * y = {2} when x = {0} and y = {1}", 1, 2, proxy.Multiply(1, 2));
Console.WriteLine("x / y = {2} when x = {0} and y = {1}", 1, 2, proxy.Divide(1, 2)); Console.ReadKey();
}

通过自定义的RealProxy创建TransparentProxy供客户端代码调用,对于通过TransparentProxy的每一次调用,都会被RealProxy接管,这样我们就可以在RealProxy中加入异常捕获、记录日志等非业务逻辑代码,这些代码在每次调用服务端方法时都会被调用。

源代码下载  (工程ConsoleHosting为服务端,工程Client3为客户端)

真实代理(RealProxy)在WCF中的运用的更多相关文章

  1. .net 自定义AOP,透明代理与真实代理

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...

  2. .net 真实代理和透明代理的交互

    .本地代理调用 using System; using System.Runtime.Remoting ; using System.Runtime.Remoting.Services ; using ...

  3. [No0000126]SSL/TLS原理详解与WCF中的WS-Security

    SSL/TLS作为一种互联网安全加密技术 1. SSL/TLS概览 1.1 整体结构 SSL是一个介于HTTP协议与TCP之间的一个可选层,其位置大致如下: SSL:(Secure Socket La ...

  4. 在Wcf中应用ProtoBuf替代默认的序列化器

    Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...

  5. WCF初探-28:WCF中的并发

    理解WCF中的并发机制 在对WCF并发机制进行理解时,必须对WCF初探-27:WCF中的实例化进行理解,因为WCF中的并发特点是伴随着服务实例上下文实现的.WCF的实例上下文模型可以通过Instanc ...

  6. WCF初探-27:WCF中的实例化

    理解WCF中的实例化机制 “实例化”是指对用户定义的服务对象以及与其相关的 InstanceContext 对象的生存期的控制.也就是说我们的客户端程序在调用服务端方法时,需要实例化一个服务端代理类对 ...

  7. WCF初探-26:WCF中的会话

    理解WCF中的会话机制 在WCF应用程序中,会话将一组消息相互关联,从而形成对话.会话”是在两个终结点之间发送的所有消息的一种相互关系.当某个服务协定指定它需要会话时,该协定会指定所有调用(即,支持调 ...

  8. WCF初探-25:WCF中使用XmlSerializer类

    前言 在上一篇WCF序列化和反序列化中,文章介绍了WCF序列化和反序列化的机制,虽然WCF针对序列化提供了默认的DataContractSerializer序列化引擎,但是WCF还支持其他的序列化引擎 ...

  9. WCF中常用的binding方式

    WCF中常用的binding方式: BasicHttpBinding: 用于把 WCF 服务当作 ASMX Web 服务.用于兼容旧的Web ASMX 服务.WSHttpBinding: 比 Basi ...

随机推荐

  1. rabbitMQ 安装 could not set correct interactive mode

    安装rabbit mq 提示下面错误 其他信息: 执行错误:C:\Program Files\erl6.0\erts-6.0\bin\erlsrv: Warning, could not set co ...

  2. sublime & atom 插件

    1. autofilename(sublime) autocomplete-paths (atom): 自动路径 2. autoprefixer: 自动添加前缀  : https://github.c ...

  3. Heap Sort

    #include<iostream> using namespace std; const int MAX = 1001; int l[MAX]; //Heap Sort void Hea ...

  4. Netty(6)源码-服务端与客户端创建

    原生的NIO类图使用有诸多不便,Netty向用户屏蔽了细节,在与用户交界处做了封装. 一.服务端创建时序图 步骤一:创建ServerBootstrap实例 ServerBootstrap是Netty服 ...

  5. package scripts在前端项目的使用

    前端的项目往往依赖了很多打包.部署工具,比如grunt,gulp,webpack.....,在这么多打包.部署工具里,有这各自的命令,这样给项目带来了很多烦恼,不同的项目不同的命令,有没有办法统一接口 ...

  6. vc++项目 : error PRJ0002 : 错误的结果 1 (从“C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\rc.exe”返回)。

    右击工程->属性->配置属性->清单工具->输入和输出->嵌入清单,把是改成否

  7. hadoop,yarn和vcpu资源配置

    Hadoop  YARN同时支持内存和CPU两种资源的调度(默认只支持内存,如果想进一步调度CPU,需要自己进行一些配置),本文将介绍YARN是如何对这些资源进行调度和隔离的. 在YARN中,资源管理 ...

  8. 基于html5 canvas 的强大图表插件【Chart.js】

    名词解释 Chart.js:是基于html5和canvas的强大图表插件,支持多样的图表形式,柱状线性饼环极地雷达等等: canvas:只兼容到IE9 excanvas.js:强大的第三方兼容插件,可 ...

  9. [SQL基础教程] 2-2 算数运算符和比较运算符

    [SQL基础教程] 2-2 算数运算符和比较运算符 算数运算符 四则运算 运算符 含义 + - * / SELECT col_1*2 AS col_new FROM table; 注意 所有包含NUL ...

  10. Abstraction elimination

    (本文不保证不误人子弟,切勿轻信) Unlambda指的是lambda计算中去掉lambda操作(does not have lambda(or abstraction) operation of t ...