- 热门文章:
- · 深度体验:windows vista最酷的五大功能
- · windows vista新功能介绍之防误删除技术
- · .NET 2.0中的企业库异常处理块简述
- · wei制度曝光:windows vista界面分五等
- · vista主题确定:aero glass风格最终获胜
- · 全新技术:windows vista系统新技术两则
- · 在.NET 2.0 中使用自定义事务操作
- · 合理攒机:如何满足vista系统的硬件需求
- · 体验windows vista图标设计功能
- · .Net Framework 2.0范型的反射使用
- · 基于VS.NET的自定项目模板研究
- · 详测:win vista beta1对p2p兼容极差
上一篇:激活windows vista 启动logo画面 >>
关于.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) { 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领域 可以将日志,事务,缓存等附加功能用此实现。
| 软件频道精品推荐 | |||
|
更多精彩 | |||
下一篇:深度体验:windows vista最酷的五大功能 >>
相关文章:
- · .NET下基于组件的分布式系统动态配置
- · 利用数据绑定和模板创建Atlas应用程序
- · 为.NET程序批上WPF的绚丽外衣
- · VS2005中文输入法自动转换的解决方法
- · VS2005与SQL Server2005的整合优势
- · VS2005改善团队开发的人力负担与协调
- · VS2005让软件开发回归软件工程
- · .NET2.0泛型的“近距离”实践
- · 基于VS.NET的自定项目模板研究
- · .NET Remoting构建分布式数据库查询
- · VS2005中用Code Snippets提高开发效率
- · 实现.NET应用程序的自动更新
- · 在.NET中使用命名管道完成进程间通信
- · 揭开.NET消息循环的神秘面纱
- · .NET设计模式研究之装饰模式
- · 浅谈CLR的内存分配和回收机制
- · .NET下的动态代码编译探索
- · 深入ASP.NET 2.0的提供者模型
- · ASP.NET 2.0编程小技巧两则
- · ASP.NET底层架构探索之进入ASP.NET
- · ASP.NET底层架构之从浏览器到ASP.NET
- · 商业周刊:即时通讯中暗藏的风险
- · 3ds max 7.5扩展版的新特色和新功能
- · 美国编程人员年薪同期增长8.7%为IT业最快
- · 金融时报:Web2.0成恶意代码的沃土
- · Web2.0时代,你得到什么?
- · 冯杰:Web2.0时代,你能得到什么?
- · 24日精选 个人网站站长常用网站推荐
- · 23日精选 Flash导航菜单轻松制作好帮手
- · 22日精选 QQ2006 Beta3开始内测
- · 21日精选 Web创业的十条戒律
- · 18日精选 AutoCAD阵列操作全攻略
- · 17日精选 Lava-Lava标签功能使用指南
- · 16日精选 穿透ADSL路由入侵内网另类伎俩
- · 15日精选 Linux下如何使用USB盘
- · 1日精选 Windows XP中轻松实现共享上网
- · 19日精选 在AutoCAD中快速精确多等分角
- · 18日精选 系统盘符错乱的解决方案
