电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

实现动态代理的介绍和使用


发布日期:2021/10/24
 

引言

假如现在我们有这样在这个示例中我将使用尽可能简单的逻辑实现所有功能需求这将更突出我们所要解决的核心问题例子是一个简单计算器类

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领域 可以将日志事务缓存等附加功能用此实现

附:本文源代码下载

上一篇:类型初始值设定项引发异常

下一篇:高亮CheckBoxList选中的项目