aop框架:轻量级AOP框架-移植python的装饰器(Decorator)到C#(研究篇)

  . 从Python说起

  Python是门强大语言它包含了很多神奇窍门技巧作为门动态语言天生优势使得很多特性让静态语言难以达到今天我们展示就是Python中个很有用特性:“Decorator”中文可以译作“装饰器”那么,Decorator是什么?

  在Dr.Dobb’s文章中有这样段描述“Decorators are Python objects that can register,annotate,and/or wrap a Python function or object.”

  具体来说Decorator就是个对封装它可以让你不改变本身情况下对执行进行干预比如在执行前进行权限认证日志记录甚至修改传入参数或者在执行后对返回结果进行预处理甚至可以截断执行等等

  看到定义是不是有熟悉感没错本质上来说它就是我们常说面向方面编程(Aspect-Oriented Programming)简称AOP相信大家对AOP也是如雷贯耳了由于动态语言本身上优势使得这类技术在动态语言平台上是如鱼得水

   2. Decorator在Python下例子

  看了很多很玄乎概念下面用个简单Python例子来具体介绍说明如何进行Decorator编程

01 def logger(name):
02     def loggerWrapper(fun):
03         def logging(self):
04             pr "User is %s." % name
05             pr "Start Logging"
06             result = fun(self)
07             pr "End Logging."
08              result
09          logging
10      loggerWrapper
11  
12 def debugger(name):
13     def debuggerWrapper(fun):
14         def debugging(self):
15             pr "Debug %s" % name
16             pr "Start Debug"
17             result = fun(self)
18             pr "End Debug"
19              result
20          debugging
21      debuggerWrapper
22  
23  MyClass:
24     @logger("Leven")
25     @debugger("test")
26     def Test(self):
27         pr("function MyClass::Test called.")
28          "I am Reuslt."
29          
30  
31  __name__  "____":
32     mc = MyClass
33     pr "Result:%s" % mc.Test


  执行改可以得到如下结果:



  回过头看看特点从源码可以了解到Decorator使用很简单直接放置在定义前即可通过@xxx方式放置系统就可以识别下面我们研究下Decorator些特点

  1. Decorator本质是它可以有传入参数它需要返回对象(注意这儿两个区别),因此名为 loggerDecorator返回了个名为loggerWrapper对象同理名为debuggerDecorator返回了个名为 debuggerWrapper对象这是Decorator定义要点:Decorator定要返回对象

  2. Decorator返回对象也是有要求这个返回对象是系统在时候执行因此系统对象时候会传入当前被装饰对象(注意这里可能并不是原始定义对象)同时需要返回个和被修饰定义供系统对比代码中定义loggerWrapper接收个fun参数很显然该参数就是当前被修饰对象同时它返回logging对象定义和被修饰完全保持

  3. 系统在被修饰思路方法时候实际上是执行了第2点介绍说明中返回对象也就是说系统会对“偷梁换柱”实际执行并不是原来定义至于原来定义体是否会执行那就要看Decorator具体实现了

  4. 对于多个Decorator情况系统会顺序进行前两步动作同时系统对Decorator处理是倒序

  下面我们再次顺序对上面例子执行方式进行介绍说明:

  首先系统检查到Test有Decorator是倒序处理所以首先针对debugger系统会直接执行debuggerWrapper并将Test作为参数fun传入debuggerWrapper执行完毕的后返回了debugging对象于是系统将Test偷换成 debugging因此如果执行Test思路方法实际执行debugging思路方法继续还有个装饰器logger同样系统会直接执行 loggerWrapper并将当前(注意当前不再是Test了经过debuger装饰Test已经被debugging 所替代因此这儿传入是debugging对象)作为参数fun传入loggerWrapper思路方法执行的后会返回logging对象定义和Test完全因此系统又将该位置debugging(Test在先前被debugging替换了)替换成logging因此在整体执行时候是直接跑去logging执行

  在上面例子中系统Test实际执行loggingloggingfun(self)实际是debugging(self)而debugging中fun(self)才是真正执行了Test思路方法

   3. 参考C#进行研究

  看到如此简单实用Decorator是不是心动了呢?想办法也让C#能享受到这个好处吧在C#中Attribute表现形式和Python很是相似因此我们考虑使用Attribute和系列相关操作来达到模拟Python执行过程

  在C#中对象由委托来进行描述因此我们考虑同样让支持Decorator操作Attribute实现个特定接口该接口返回个委托然后将实际执行该思路方法时候去执行该委托那么考虑以下形式:

01 public  MyClass{
02     [Logger(“Leven”)]
03     public  Test( s) {
04         xxx
05          xxx;
06     }
07 }
08  
09 public delegate  TestMethodDelegate( s);
10  
11 public  LoggerAttribute : Attribute {
12     public  Name { get; private ; }
13  
14     public LoggerAttribute( name) {
15         Name = name;
16     }
17  
18     TestMethodDelegate LoggerWrapper(TestMethodDelegate fun) {
19          e => {
20             Console.WriteLine(“User is {0}.”, Name);
21             Console.WriteLine(“Start Logging”);
22             var result = Fun(e);
23             Console.WriteLine(“End Logging”);
24              result;
25         }
26     }
27 }


  这样来形式就和PythonDecorator大致样了然而在正常情况下C#是不会像Python样自动处理 LoggerAttribute和Test关系因此LoggerWrapper永远也没法执行更不用说替换Test思路方法了于是下面我们需要继续考虑具体功能实现

   4. 考虑功能实现

  要实现Decorator很重要点就是能做到对思路方法“偷梁换柱”而C#在运行期是不能修改思路方法当然Decorator本质上是种AOP表现形式因此我们大可考虑AOP常见实现方式AOP般有动态代理和静态织入两种实现方式动态代理虽然有些小小限制但是相比静态织入实现和使用上都大大简单化因此我们考虑使用动态代理方式实现该功能

  对于MyClass类我们希望能生成个新MyClassWrapper类该类继承自MyClass同时我们要求将Test思路方法修改成 virtual思路方法这样我们可以在MyClassWrapper类中对Test思路方法进行改写这样以来就达到了对思路方法“偷梁换柱”做法虽然比起 Python不够利索但是能满足我们要求也是大大欢迎那么我们MyClassWrapper类要求如下定义:

1 public  MyClassWrapper : MyClass {
2     public override  Test {
3         LoggerAttribute attribute =
4 typeof(MyClass).GetMethod(“Test”).GetCustomAttribute(typeof(LoggerAttribute), true)[0] as LoggerAttribute; //获取基类中个LoggerAttribute
5         //LoggerWrapper思路方法,获取新委托.
6         var fun = attribute.LoggerWrapper( TestMethodDelegate(Test));
7          fun;
8     }
9 }




  这样我们就改写了Test思路方法实现达到和Python中Decorator效果然而C#这种处理方式还是和Python有区别在Python中是Decorator替换掉被装饰但是在C#中思路方法不能被另个委托对象替换我们只能在思路方法内部手动执行装饰过思路方法不过效果是完全当然上面例子只是代表了种实现思路方法在多个Attribute情况下还需要很多区别处理不过这样就代表在C#上实现pythonDecorator是完全行得通

  在上面例子中我们针对Test思路方法做到了装饰但是作为个框架我们要求能对所有满足要求思路方法都能实现装饰因此我们需要对上面实现进行修改很重要我们上面装饰器仅仅能处理 Test()这样思路方法如果是 Test(object)我们则需要重新定义使用可是大大不便于是考虑用种通用思路方法签名来代表所有思路方法也就是使用 Func<object, object, object>来代表任意思路方法

   5. 本篇小结

  在本篇中我们将Python中Decorator原理进行了透彻分析同时评估了在C#实现同样Decorator可行性通过分析可以肯定在C#上通过技术手段我们完全可以实现和Python类似Decorator功能

  在下篇中文章将从具体实战出发对PythonDecorator进行个完整移植因此篇将暂定名为“编码篇”



Tags:  什么是轻量级框架 轻量级框架 .netaop框架 aop框架

延伸阅读

最新评论

发表评论