用 Roslyn 做个 JIT 的 AOP
-0.1 系列目录
0. 前言
副标题:无价值人生记录.0:浪费 1000% 时间去做一个用来节省 1% 时间的“轮子玩具”(下:AOP实践1 JIT)
上接:AOP有几种实现方式 https://xie.infoq.cn/article/6f65df715a020c0b77f4cd266
接下来说说怎么做AOP的demo,先用csharp 说下动态编织和静态编织,有时间再说点java的对应内容。
第一篇先说Roslyn 怎么做个JIT的AOP demo。
为啥这样讲呢?
实际是因为Roslyn 已经包含了JIT的全部部分,那我也就不用说任何JIT的实现了。(真爽)
所以本篇实际说的是以下这些内容:
怎么引入Roslyn做JIT编译代码
代理模式的AOP是什么样
为什么不推荐在生产环境这样玩?
1. JIT编译代码
Roslyn 是.NET的编译器,感兴趣的可以参见文档 https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/
实际上Roslyn已经做的非常简单了,几行代码引入进来就可以编译csharp代码了。
不信我们就手把手写一个
1.1 引入Roslyn包
1.2 代码转化为语法树
1.3 准备编译器实例
1.4 编译到内存中
1.5 测试一下
运行结果:
HiJ
Hi, joker!
就这么简单,你就可以JIT了,想干什么都可以了。
2. 用代理方式实现AOP
2.1 回顾代理是什么
这里单独再说一下代理是什么,
毕竟很多AOP框架或者其他框架都有利用代理的思想,
为什么都要这样玩呢?
很简单,代理就是帮你做相同事情,并且可以比你做的更多,还一点儿都不动到你原来的代码。
比如如下 真实的class 和代理class 看起来一模一样
但两者的真实的代码可能是这样子的
RealClass:
ProxyClass:
所以我们调用的时候会是这样
2.2 做一个Proxy代码生成器
那么我们来做一个上面例子中能生成一模一样的ProxyClass 代码生成器
首先,我们都知道 csharp 再运行中可以反射获取元数据(反编译出代码也可以做,就是我们杀鸡用牛刀呢?)
我们知道了元数据,就可以拼字符串拼出我们想要的代码(对,你没看错,我们拼字符串就够了)
废话不说, show you code
测试一下
结果:
public class RealClassProxy : RealClass { public override System.Int32 Add(System.Int32 i,System.Int32 j) {System.Int32 r = default;r = base.Add(i,j);r++;return r; } }
2.3 结合在一起测试一下
结果为:
5 + 10 = 15, but proxy is 16
是的,我们写了这么多代码就是为了让 15 变成 16 ,让别人不知道 多了个 r++;
,这就是AOP的意义
完整的demo 放在 https://github.com/fs7744/AopDemoList
2.4 再完善完善就可以了。。。(也就再写个几年)
你只需要完善如下:
支持 void 方法
支持 async await 方法
支持抽象类
支持接口
支持构造方法
支持属性
支持索引器
支持 in out ref
支持泛型
支持嵌套类
支持剩下的各种各样情况
嗯,相信你自己,你可以的
3. 不推荐在生产环境这样玩,为什么?
3.1 两幅图
手写的proxy :
jit 编译proxy:
随着需要编译的Proxy class 增多, cpu 和 内存都会一样增多
3.2 你信不信得过调用你api的对方
嗯,这是一个信任度的问题,
只要对方可信,Roslyn sdk api 别人是不会调用的哦
但是我们都知道前人们都告诉我们有个准则:不要相信任何Input。
所以大家的猫主子会不会跟着别人跑掉就看大家信心和手段了。
版权声明: 本文为 InfoQ 作者【八苦-瞿昙】的原创文章。
原文链接:【http://xie.infoq.cn/article/93933c69ca17f31f81abe4441】。文章转载请联系作者。
评论 (3 条评论)