当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > 关于.NET动态代理的介绍和应用简介

ASP.NET
C# Quoted-Printable编码、解码
asp.net Google的translate工具翻译 API
.NET读取所有目录下文件正则匹配文本电子邮件
asp.net 半角全角转化工具
AjaxControlToolKit 显示浏览者本地语言的方法
asp.net HTML文件上传标签
ASP.NET 绑定DataSet中的多个表
ASP.NET 重定向的几种方法小结
Asp.Net 重定向必须要知道的一些资料
ASP.NET 导出到Excel时保留换行的代码
Asp.Net Cache缓存使用代码
document.getElementsByName和document.getElementById 在IE与FF中不同实现
GridView单元格合并
asp.net 大文件上传控件
asp.net 日期函数 某月的第一天和最后一天的日期
asp.net 时间类 一周的周一和周末的日期
C# javaScript函数的相互调用
asp.net membership 密码重设
"虚拟路径"..."映射到另一个应用程序,这是不允许的!
如何传值在2个页面之间 要求不刷新父页面,并且不能用Querystring传值

ASP.NET 中的 关于.NET动态代理的介绍和应用简介


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-13   浏览: 145 ::
收藏到网摘: n/a

  引言
  假如现在我们有这样在这个示例中我将使用尽可能简单的逻辑实现所有功能需求,这将更突出我们所要解决的核心问题。例子是一个简单计算器类:
public class Calculator
{
 public int Add(int x, int y) { return x + y; }
}

  这个类再简单不过了,不过若你将它想象为一个可能更复杂的业务处理类的时候,你将面临除了核心功能实现之外的更多处理细节,比如说:权限控制、审计日志、性能监测、缓冲处理、事务环境等等。为简单起见,我们首先为该类增加记录日志的功能,该功能要求将对每个方法的调用和处理结果输出到Console中,如下:
public class Calculator
{
 public int Add(int x, int y)
 {
  Console.Write("Add({0},{1})", x, y);
  int result = x + y;
  Console.WriteLine(" = {0}", result);
  return result;
 }
}

  再简单不过了,对吧?现在我们需要为该方法实现性能监测,如下:
public class Calculator
{
 public int Add(int x, int y)
 {
  Console.Write("Add({0},{1})", x, y);
  DateTime TimeBegin = System.DateTime.Now;
  int result = x + y;
  TimeSpan TimeInter =System.DateTime.Now-TimeBegin;
  Console.Write(" [{0}] ", TimeInter);
  Console.WriteLine(" = {0}", result);
  return result;
 }
}

  此时你已经感觉到,虽然我们实现了所需的功能,但是在一个方法中堆叠了处理各类事宜的不同代码。虽然在这个简单例子中不会感觉有什么不爽,但是请你想象一下如果我们将为该类添加第二个方法时会发生什么事情:
public class Calculator
{
 public int Add(int x, int y)
 {
  Console.Write("Add({0},{1})", x, y);
  DateTime TimeBegin = System.DateTime.Now;
  int result = x + y;
  TimeSpan TimeInter =System.DateTime.Now-TimeBegin;
  Console.Write(" [{0}] ", TimeInter);
  Console.WriteLine(" = {0}", result);
  return result;
 }
 public int Subtract(int x, int y)
 {
  Console.Write("Subtract({0},{1})", x, y);
  DateTime TimeBegin = System.DateTime.Now;
  int result = x - y;
  TimeSpan TimeInter =System.DateTime.Now-TimeBegin;
  Console.Write(" [{0}] ", TimeInter);
  Console.WriteLine(" = {0}", result);
  return result;
 }
}

  在两个方法中已经明显出现重复代码了,这可不是一个好的解决办法——想想一下如果我们的计算器有10个方法呢?如果我们还有类似于计算器类的另外数十个类呢?如果我们还有更多的方法级功能要实现呢(权限控制、事务管理……)?在企业级应用开发中,这可是一个经常会遇的问题。为清楚起见,我们将问题分解成两部分,首要的问题是代码职责混淆,其次则是同样的代码逻辑反复多次——这些问题都将导致开发管理、代码编写与维护的各种困难。
  方案一:自己手动编写代理解决
  1、首先 我们定义接口ICalculator:
using System;
namespace Proxy
{
 public interface ICalculator
 {
  int Add(int x, int y);
  int Subtract(int x, int y);
 }
}

  2、具体实现一个接口:
using System;
namespace Proxy
{
 public class Calculator:ICalculator
 {
  public virtual int Add(int x, int y)
  {
   int result = x + y;
   return result;
  }
  public virtual int Subtract(int x, int y)
  {
   int result = x - y;
   return result;
  }
 }
}
  3、编写增加日志和性能检测功能的代理类
  增加记录日志的功能,即功能要求将对每个方法的调用和处理结果输出到Console;增加性能监测。
  有两种实现方式 ,注释了其中的一种
using System;
namespace Proxy
{
 // /// <summary>
 // /// CalProxy 的摘要说明。
 // /// </summary>
 // public class CalProxy:ICalculator
 // {
 // private Calculator _Calculator;
 // public CalProxy()
 // {
 // this._Calculator=new Calculator();
 // }
 // private DateTime TimeBegin = System.DateTime.Now;
 // private void PreDoSomething(int x, int y)
 // {
 // TimeBegin = System.DateTime.Now;
 // Console.Write("Number({0},{1})\n", x, y);
 // }
 // //实现add
 // public virtual int Add(int x, int y)
 // {
 // this.PreDoSomething(x,y);
 // int result = this._Calculator.Add(x,y);
 // this.PostDoSomething(result);
 // return result;
 // }
 // //实现sub
 // public virtual int Subtract(int x, int y)
 // {
 // this.PreDoSomething(x,y);
 // int result = this._Calculator.Subtract(x,y);
 // this.PostDoSomething(result);
 // return result;
 // }
 // private void PostDoSomething(int result)
 // {
 // TimeSpan TimeInter =System.DateTime.Now-TimeBegin;
 // Console.Write(" 运行时间[{0}]\n ", TimeInter);
 // Console.WriteLine(" 运行结果= {0}\n", result);
 // }
 // }
 /// <summary>
 /// CalProxy 的摘要说明。
 /// </summary>
 public class CalProxy:Calculator
 {
  public CalProxy()
  {}
  private DateTime TimeBegin = System.DateTime.Now;
  private void PreDoSomething(int x, int y)
  {
   TimeBegin = System.DateTime.Now;
   Console.Write("Number({0},{1})\n", x, y);
  }
  //实现add
  public override int Add(int x, int y)
  {
   this.PreDoSomething(x,y);
   int result = base.Add(x,y);
   this.PostDoSomething(result);
   return result;
  }
  //实现sub
  public override int Subtract(int x, int y)
  {
   this.PreDoSomething(x,y);
   int result = base.Subtract(x,y);
   this.PostDoSomething(result);
   return result;
  }
  private void PostDoSomething(int result)
  {
   TimeSpan TimeInter =System.DateTime.Now-TimeBegin;
   Console.Write(" 运行时间[{0}]\n ", TimeInter);
   Console.WriteLine(" 运行结果= {0}\n", result);
  }
 }
}

  4、外界的调用方式
ICalculator ICal=new Proxy.CalProxy();
ICal.Add(5,3);
ICal.Subtract(7,2);

  运行程序的结果:
Number(5,3)
  运行时间[00:00:02.0156250]
  运行结果= 8
  Number(7,2)
  运行时间[00:00:03]
  运行结果= 5
  方案二:通过使用Castle.DynamicProxy,实现Iinterceptor解决
  步骤1,2与解决问题
  3、实现StandardInterceptor,增加日志和性能监测功能
  StandardInterceptor是接口Iinterceptor的一个实现类,我们实现StandardInterceptor
using System;
using System.Collections;
using Castle.DynamicProxy;
namespace Proxy
{
 /// <summary>
 /// ProxyInterceptor 拦截器 实现了日志和性能监测
 /// </summary>
 public class ProxyInterceptor:StandardInterceptor
 {
  private System.DateTime TimeBegin=System.DateTime.Now;
  public ProxyInterceptor()
  {}
  protected override void PostProceed(IInvocation invocation, ref object returnValue, params object[] arguments)
  {
   TimeSpan TimeInter =System.DateTime.Now-TimeBegin;
   Console.Write(" 运行时间[{0}]\n ", TimeInter);
   Console.WriteLine(" 运行结果= {0}\n", returnValue);
   base.PostProceed(invocation, ref returnValue, arguments);
  }
  protected override void PreProceed(IInvocation invocation, params object[] args)
  {
   Console.Write("Number({0},{1})\n", args[0], args[1]);
   TimeBegin=System.DateTime.Now;
   base.PreProceed(invocation, args);
  }
  public override object Intercept(IInvocation invocation, params object[] args)
  {
   PreProceed(invocation, args);
   object retValue = invocation.Proceed( args );
   PostProceed(invocation, ref retValue, args);
   return retValue;
  }
 }
}

  4、使用Castle.DynamicProxy调用
ProxyGenerator generator = new ProxyGenerator();
object proxy = generator.CreateClassProxy(typeof(Calculator), new ProxyInterceptor());
ICalculator ICalCastle=proxy as ICalculator;
ICalCastle.Add(5,3);
ICalCastle.Subtract(7,2);


  实现过程:首先通过代码生成完成一个代理类,该代理类继承自要织入的类。然后在代理类中覆盖要拦截的方法,并在覆盖的方法中封装Invocation对象,并传给用户传入的Intercepter对象的Intercept方法。在Intercept方法依次调用Intercepter的PreProcess,通过Invocation传入的Delegate指向的回调函数,Intercepter的PostProcess方法,从而达到拦截的目的。
  意义
  在aop领域 可以将日志,事务,缓存等附加功能用此实现。