熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

實現動態代理的介紹和使用

2022-06-13   來源: .NET編程 

  引言
  假如現在我們有這樣在這個示例中我將使用盡可能簡單的邏輯實現所有功能需求這將更突出我們所要解決的核心問題例子是一個簡單計算器類

  public class Calculator
{
  public int Add(int x int y) { return x + y; }
}

  這個類再簡單不過了不過若你將它想象為一個可能更復雜的業務處理類的時候你將面臨除了核心功能實現之外的更多處理細節比如說權限控制審計日志性能監測緩沖處理事務環境等等為簡單起見我們首先為該類增加記錄日志的功能該功能要求將對每個方法的調用和處理結果輸出到Console中如下

  public class Calculator
{
  public int Add(int x int y)
  {
    ConsoleWrite(Add({}{}) x y);
    int result = x + y;
    ConsoleWriteLine( = {} result);
    return result;
  }
}

  再簡單不過了對吧?現在我們需要為該方法實現性能監測如下

  public class Calculator

  {

  public int Add(int x int y)

  {

  ConsoleWrite(Add({}{}) x y);

  DateTime TimeBegin = SystemDateTimeNow;

  int result = x + y;

  TimeSpan TimeInter =SystemDateTimeNowTimeBegin;

  ConsoleWrite( [{}] TimeInter);

  ConsoleWriteLine( = {} result);

  return result;

  }

  }

  此時你已經感覺到雖然我們實現了所需的功能但是在一個方法中堆疊了處理各類事宜的不同代碼雖然在這個簡單例子中不會感覺有什麼不爽但是請你想象一下如果我們將為該類添加第二個方法時會發生什麼事情

  public class Calculator

  {

  public int Add(int x int y)

  {

  ConsoleWrite(Add({}{}) x y);

  DateTime TimeBegin = SystemDateTimeNow;

  int result = x + y;

  TimeSpan TimeInter =SystemDateTimeNowTimeBegin;

  ConsoleWrite( [{}] TimeInter);

  ConsoleWriteLine( = {} result);

  return result;

  }

  public int Subtract(int x int y)

  {

  ConsoleWrite(Subtract({}{}) x y);

  DateTime TimeBegin = SystemDateTimeNow;

  int result = x y;

  TimeSpan TimeInter =SystemDateTimeNowTimeBegin;

  ConsoleWrite( [{}] TimeInter);

  ConsoleWriteLine( = {} result);

  return result;

  }

  在兩個方法中已經明顯出現重復代碼了這可不是一個好的解決辦法——想想一下如果我們的計算器有個方法呢?如果我們還有類似於計算器類的另外數十個類呢?如果我們還有更多的方法級功能要實現呢(權限控制事務管理……)?在企業級應用開發中這可是一個經常會遇的問題為清楚起見我們將問題分解成兩部分首要的問題是代碼職責混淆其次則是同樣的代碼邏輯反復多次——這些問題都將導致開發管理代碼編寫與維護的各種困難

  方案一自己手動編寫代理解決
  首先 我們定義接口ICalculator
using System;

  namespace Proxy

  {

  public interface ICalculator

  {

  int Add(int x int y);

  int Subtract(int x int y);

  }

    具體實現一個接口
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;

  }

  }

  }

    編寫增加日志和性能檢測功能的代理類
增加記錄日志的功能即功能要求將對每個方法的調用和處理結果輸出到Console增加性能監測

  有兩種實現方式 注釋了其中的一種

  using System;

  namespace Proxy

  {

  //   ///

  //   /// CalProxy 的摘要說明

  //   ///

  //   public class CalProxy:ICalculator

  //   {

  //        private Calculator _Calculator;

  //       public CalProxy()

  //       {

  //            this_Calculator=new Calculator();

  //       }

  //        private DateTime TimeBegin = SystemDateTimeNow;

  //        private void  PreDoSomething(int x int y)

  //       {

  //          TimeBegin = SystemDateTimeNow;

  //            ConsoleWrite(Number({}{})\n x y);

  //       }

  //       //實現add

  //       public virtual  int Add(int x int y)

  //       {

  //            thisPreDoSomething(xy);

  //            int result = this_CalculatorAdd(xy);

  //           thisPostDoSomething(result);

  //            return result;

  //       }

  //       //實現sub

  //       public virtual int Subtract(int x int y)

  //       {

  //            thisPreDoSomething(xy);

  //            int result = this_CalculatorSubtract(xy);

  //            thisPostDoSomething(result);

  //            return result;

  //       }

  //        private void PostDoSomething(int result)

  //       {

  //            TimeSpan TimeInter =SystemDateTimeNowTimeBegin;

  //            ConsoleWrite( 運行時間[{}]\n TimeInter);

  //            ConsoleWriteLine( 運行結果= {}\n result);

  //       }

  //   }

  ///

  /// CalProxy 的摘要說明

  ///

  public class CalProxy:Calculator

  {

  public CalProxy()

  {

  }

  private DateTime TimeBegin = SystemDateTimeNow;

  private void  PreDoSomething(int x int y)

  {

  TimeBegin = SystemDateTimeNow;

  ConsoleWrite(Number({}{})\n x y);

  }

  //實現add

  public override  int Add(int x int y)

  {

  thisPreDoSomething(xy);

  int result = baseAdd(xy);

  thisPostDoSomething(result);

  return result;

  }

  //實現sub

  public override int Subtract(int x int y)

  {

  thisPreDoSomething(xy);

  int result = baseSubtract(xy);

  thisPostDoSomething(result);

  return result;

  }

  private void PostDoSomething(int result)

  {

  TimeSpan TimeInter =SystemDateTimeNowTimeBegin;

  ConsoleWrite( 運行時間[{}]\n TimeInter);

  ConsoleWriteLine( 運行結果= {}\n result);

  }

  }

    外界的調用方式
ICalculator  ICal=new ProxyCalProxy();

  ICalAdd();

  ICalSubtract();

  運行程序的結果

  Number()

  運行時間[::]

  運行結果=

  Number()

  運行時間[::]

  運行結果=

  方案二通過使用CastleDynamicProxy實現Iinterceptor解決
步驟 與解決問題
實現StandardInterceptor增加日志和性能監測功能
StandardInterceptor是接口Iinterceptor的一個實現類我們實現StandardInterceptor

  using System;

  using SystemCollections;

  using CastleDynamicProxy;

  namespace Proxy

  {

  ///

  /// ProxyInterceptor 攔截器  實現了日志和性能監測

  ///

  public class ProxyInterceptor:StandardInterceptor

  {

  private  SystemDateTime TimeBegin=SystemDateTimeNow;

  public ProxyInterceptor()

  {

  }

  protected override void PostProceed(IInvocation invocation ref object returnValue params object[] arguments)

  {

  TimeSpan TimeInter =SystemDateTimeNowTimeBegin;

  ConsoleWrite( 運行時間[{}]\n TimeInter);

  ConsoleWriteLine( 運行結果= {}\n returnValue);

  basePostProceed(invocation ref returnValue arguments);

  }

  protected override void PreProceed(IInvocation invocation params object[] args)

  {

  ConsoleWrite(Number({}{})\n args[] args[]);

  TimeBegin=SystemDateTimeNow;

  basePreProceed(invocation args);

  }

  public override object Intercept(IInvocation invocation params object[] args)

  {

  PreProceed(invocation args);

  object retValue = invocationProceed( args );

  PostProceed(invocation ref retValue args);

  return retValue;

  }

  }

  }

  使用CastleDynamicProxy調用
ProxyGenerator generator = new ProxyGenerator();

  object proxy = generatorCreateClassProxy(typeof(Calculator) new ProxyInterceptor());

  ICalculator  ICalCastle=proxy as ICalculator;

  ICalCastleAdd();

  ICalCastleSubtract();

  實現過程首先通過代碼生成完成一個代理類該代理類繼承自要織入的類然後在代理類中覆蓋要攔截的方法並在覆蓋的方法中封裝Invocation對象並傳給用戶傳入的Intercepter對象的Intercept方法在Intercept方法依次調用Intercepter的PreProcess通過Invocation傳入的Delegate指向的回調函數Intercepter的PostProcess方法從而達到攔截的目的

  意義
  在aop領域 可以將日志事務緩存等附加功能用此實現

  附:本文源代碼下載


From:http://tw.wingwit.com/Article/program/net/201311/12954.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.