在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. CentOS在线升级内核

    升级内核需要使用 elrepo 的yum 源首先我们导入 elrepo 的key  rpm –import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org ...

  2. 将前台input中的数据异步传到后台并存入数据库

    将前台input中的数据异步传到后台并存入数据库 先看图: 利用ajax异步交互数据,并不是以json数组的形式将数据传到后台,而是利用字符数组的形式将其传到后台.动态新增每一行数据,将每一列对应的数 ...

  3. Unity在安卓的一些路径

    APK安装之后找不到路径 公司的测试机(安卓)基本都是不带SD卡的. APK在安卓手机上安装之后,使用手机助手类的软件打开文件管理,打开 内置SDK卡/Android/data/ 在这个目录下却发现 ...

  4. 2016 ACM/ICPC Asia Regional Qingdao Online 1001 I Count Two Three

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...

  5. html5的navigator调用手机震动

    navigator.vibrate(s) 或 navigator.webkitVibrate(s),不过该属性只在安卓系统有效.

  6. Vim扩展YouCompleteMe插件

    在Vim中安装YouCompleteMe插件 一.安装前的说明: 1.确保vim版本>=7.4,若MAC OS,建议直接安装MacVim(8.0版本). ps:如果不想使用MacVim的GUI, ...

  7. webservices(一)

    ---完全摘自网络 什么是webService WebService,顾名思义就是基于Web的服务.它使用Web(HTTP)方式,接收和响应外部系统的某种请求.从而实现远程调用.  1:从WebSer ...

  8. [6278009]使用Visual Stuido Code 编写Markdown

    使用Visual Stuido Code 编写Markdown void main() { printf("Hello world!"); } void main() { Cons ...

  9. [UWP小白日记-3]记账项目-1

    学了一段时间的UWP,来个项目试试手. 本来是想边做边学MVVMLight的结果感觉MVVM对于萌新来说太高难,以后再把这个项目改造成MVVMLight框架的项目. 下面进入正题. 中间那快空白打算放 ...

  10. 第八章 监控 Zabbix

    1.1   YUM部署 Zabbix 2.4 1.  前期准备(省略) l   Yum源的配置 cd /etc/yum.repos.d/; mkdir old;mv ./* old/ rpm -Uvh ...