关于.NET动态代理的介绍和应用简介
2023-06-13 09:13:42 时间
引言
假如现在我们有这样在这个示例中我将使用尽可能简单的逻辑实现所有功能需求,这将更突出我们所要解决的核心问题。例子是一个简单计算器类:
publicclassCalculator
{
publicintAdd(intx,inty){returnx+y;}
}
假如现在我们有这样在这个示例中我将使用尽可能简单的逻辑实现所有功能需求,这将更突出我们所要解决的核心问题。例子是一个简单计算器类:
{
publicintAdd(intx,inty){returnx+y;}
}
这个类再简单不过了,不过若你将它想象为一个可能更复杂的业务处理类的时候,你将面临除了核心功能实现之外的更多处理细节,比如说:权限控制、审计日志、性能监测、缓冲处理、事务环境等等。为简单起见,我们首先为该类增加记录日志的功能,该功能要求将对每个方法的调用和处理结果输出到Console中,如下:
{
publicintAdd(intx,inty)
{
Console.Write("Add({0},{1})",x,y);
intresult=x+y;
Console.WriteLine("={0}",result);
returnresult;
}
}
再简单不过了,对吧?现在我们需要为该方法实现性能监测,如下:
{
publicintAdd(intx,inty)
{
Console.Write("Add({0},{1})",x,y);
DateTimeTimeBegin=System.DateTime.Now;
intresult=x+y;
TimeSpanTimeInter=System.DateTime.Now-TimeBegin;
Console.Write("[{0}]",TimeInter);
Console.WriteLine("={0}",result);
returnresult;
}
}
此时你已经感觉到,虽然我们实现了所需的功能,但是在一个方法中堆叠了处理各类事宜的不同代码。虽然在这个简单例子中不会感觉有什么不爽,但是请你想象一下如果我们将为该类添加第二个方法时会发生什么事情:
{
publicintAdd(intx,inty)
{
Console.Write("Add({0},{1})",x,y);
DateTimeTimeBegin=System.DateTime.Now;
intresult=x+y;
TimeSpanTimeInter=System.DateTime.Now-TimeBegin;
Console.Write("[{0}]",TimeInter);
Console.WriteLine("={0}",result);
returnresult;
}
publicintSubtract(intx,inty)
{
Console.Write("Subtract({0},{1})",x,y);
DateTimeTimeBegin=System.DateTime.Now;
intresult=x-y;
TimeSpanTimeInter=System.DateTime.Now-TimeBegin;
Console.Write("[{0}]",TimeInter);
Console.WriteLine("={0}",result);
returnresult;
}
}
在两个方法中已经明显出现重复代码了,这可不是一个好的解决办法——想想一下如果我们的计算器有10个方法呢?如果我们还有类似于计算器类的另外数十个类呢?如果我们还有更多的方法级功能要实现呢(权限控制、事务管理……)?在企业级应用开发中,这可是一个经常会遇的问题。为清楚起见,我们将问题分解成两部分,首要的问题是代码职责混淆,其次则是同样的代码逻辑反复多次——这些问题都将导致开发管理、代码编写与维护的各种困难。
方案一:自己手动编写代理解决
1、首先我们定义接口ICalculator:
namespaceProxy
{
publicinterfaceICalculator
{
intAdd(intx,inty);
intSubtract(intx,inty);
}
}
2、具体实现一个接口:
namespaceProxy
{
publicclassCalculator:ICalculator
{
publicvirtualintAdd(intx,inty)
{
intresult=x+y;
returnresult;
}
publicvirtualintSubtract(intx,inty)
{
intresult=x-y;
returnresult;
}
}
} 3、编写增加日志和性能检测功能的代理类
增加记录日志的功能,即功能要求将对每个方法的调用和处理结果输出到Console;增加性能监测。
有两种实现方式,注释了其中的一种
namespaceProxy
{
/////<summary>
/////CalProxy的摘要说明。
/////</summary>
//publicclassCalProxy:ICalculator
//{
//privateCalculator_Calculator;
//publicCalProxy()
//{
//this._Calculator=newCalculator();
//}
//privateDateTimeTimeBegin=System.DateTime.Now;
//privatevoidPreDoSomething(intx,inty)
//{
//TimeBegin=System.DateTime.Now;
//Console.Write("Number({0},{1})\n",x,y);
//}
////实现add
//publicvirtualintAdd(intx,inty)
//{
//this.PreDoSomething(x,y);
//intresult=this._Calculator.Add(x,y);
//this.PostDoSomething(result);
//returnresult;
//}
////实现sub
//publicvirtualintSubtract(intx,inty)
//{
//this.PreDoSomething(x,y);
//intresult=this._Calculator.Subtract(x,y);
//this.PostDoSomething(result);
//returnresult;
//}
//privatevoidPostDoSomething(intresult)
//{
//TimeSpanTimeInter=System.DateTime.Now-TimeBegin;
//Console.Write("运行时间[{0}]\n",TimeInter);
//Console.WriteLine("运行结果={0}\n",result);
//}
//}
///<summary>
///CalProxy的摘要说明。
///</summary>
publicclassCalProxy:Calculator
{
publicCalProxy()
{}
privateDateTimeTimeBegin=System.DateTime.Now;
privatevoidPreDoSomething(intx,inty)
{
TimeBegin=System.DateTime.Now;
Console.Write("Number({0},{1})\n",x,y);
}
//实现add
publicoverrideintAdd(intx,inty)
{
this.PreDoSomething(x,y);
intresult=base.Add(x,y);
this.PostDoSomething(result);
returnresult;
}
//实现sub
publicoverrideintSubtract(intx,inty)
{
this.PreDoSomething(x,y);
intresult=base.Subtract(x,y);
this.PostDoSomething(result);
returnresult;
}
privatevoidPostDoSomething(intresult)
{
TimeSpanTimeInter=System.DateTime.Now-TimeBegin;
Console.Write("运行时间[{0}]\n",TimeInter);
Console.WriteLine("运行结果={0}\n",result);
}
}
}
4、外界的调用方式
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
usingSystem.Collections;
usingCastle.DynamicProxy;
namespaceProxy
{
///<summary>
///ProxyInterceptor拦截器实现了日志和性能监测
///</summary>
publicclassProxyInterceptor:StandardInterceptor
{
privateSystem.DateTimeTimeBegin=System.DateTime.Now;
publicProxyInterceptor()
{}
protectedoverridevoidPostProceed(IInvocationinvocation,refobjectreturnValue,paramsobject[]arguments)
{
TimeSpanTimeInter=System.DateTime.Now-TimeBegin;
Console.Write("运行时间[{0}]\n",TimeInter);
Console.WriteLine("运行结果={0}\n",returnValue);
base.PostProceed(invocation,refreturnValue,arguments);
}
protectedoverridevoidPreProceed(IInvocationinvocation,paramsobject[]args)
{
Console.Write("Number({0},{1})\n",args[0],args[1]);
TimeBegin=System.DateTime.Now;
base.PreProceed(invocation,args);
}
publicoverrideobjectIntercept(IInvocationinvocation,paramsobject[]args)
{
PreProceed(invocation,args);
objectretValue=invocation.Proceed(args);
PostProceed(invocation,refretValue,args);
returnretValue;
}
}
}
4、使用Castle.DynamicProxy调用
objectproxy=generator.CreateClassProxy(typeof(Calculator),newProxyInterceptor());
ICalculatorICalCastle=proxyasICalculator;
ICalCastle.Add(5,3);
ICalCastle.Subtract(7,2);
实现过程:首先通过代码生成完成一个代理类,该代理类继承自要织入的类。然后在代理类中覆盖要拦截的方法,并在覆盖的方法中封装Invocation对象,并传给用户传入的Intercepter对象的Intercept方法。在Intercept方法依次调用Intercepter的PreProcess,通过Invocation传入的Delegate指向的回调函数,Intercepter的PostProcess方法,从而达到拦截的目的。
意义
在aop领域可以将日志,事务,缓存等附加功能用此实现。
相关文章
- ASP.NET DropDownList1_SelectedIndexChanged使用
- .NET跨平台框架选择之一 - Avalonia UI
- .net 温故知新:【8】.NET 中的配置从xml转向json
- ASP.NET WEB项目中GridView与Repeater数据绑定控件的用法
- 联手开发:.NET与Oracle的合作之路(.net和oracle)
- 程序员级别鉴定书(.NET面试问答集锦)
- Net访问Oracle数据库的简易方法(.net访问oracle)
- NET环境下操作Oracle数据库的技巧(.net操作oracle)
- NET环境下 MySQL数据库应用实践(.net配合 mysql)
- Net结合MySQL实现强劲的数据库运算(.net 用mysql)
- 网上解决Net环境下MySQL数据库的同步问题(.net 同步mysql)
- Net中连接MySQL技术简述(.net中引用mysql)
- 分类NET 5与MySQL分类新加坡开发者技术展望(.net 5 mysql)
- ASP.NET页面间的传值的几种方法
- asp.net用继承方法实现页面判断session
- ASP.NET前后台调用方法
- 鼠标右击事件代码(asp.net后台)
- asp.net中不能在DropDownList中选择多个项原因分析及解决方法
- ASP.NET的事件模型(很适合学习的文章)
- asp.net多选项卡页面的创建及使用方法
- 获取客户端IP地址c#/vb.net各自实现代码
- C#.net中的类型转换详细介绍
- c#.NET写txt文件小例子
- .NET基础之自定义泛型分析
- ASP.NET使用application与session对象写的简单聊天室程序