方法级AOP: 又一个补丁

 当前版本的地址如下:

https://files.cnblogs.com/guaiguai/FuncTest.zip

这个小例子可以看作方法级的AOP, 包里是一种实现方法, 利用了新的Expression, 比起生成动态代理类的做法那是清凉多了(当然, 也可以以这个为基础, 组合出复杂的方式,或者和生成动态代理类互补), 使用起来也灵活, 就是表达方式有点丑, 比如这样:

string c = "fuck";

MethodCall.Extract(() 
=> bar.DoSomething(c)).Invoke();

有返回时(上面的DoSomething是实例的方法, 下面这个是静态方法):

int a = 3;
int b = 4;

 List
<int> list1 = MethodCall.Extract(() => Foo.DoSomething(a, "hello", b)).FromCache().Invoke();


其中使用“()=>”这样的表达式写法是为了提取足够的信息, 包括方法、 实例和参数, FromCache这样的东西当然要自己扩展啦, 上面的包里有一个简单的例子; 而Invoke则触发它执行。

其实FromCache这样的Extension并不好, 如果这样扩展,那么使用时“FromCache().Log().CheckAccess().....Invoke()”这样臃肿的写法就会大量重复; 这里我有一个重构的方式, 不过想先听听大家的意见, 所以暂时卖个关子。

上面提到的重构,还有帮助组合的辅助设施,包括搭配使用的动态代理类生成器,  我暂时都不打算实现, 做全了工作量比较大, 同时很可能就又成了一个框架了。 最近一段时间,我个人对框架式的做法比较谨慎, 拿出这个轻薄短小的例子, 也是想先讨论一下。

这是跟老赵还有脑袋讨论的成果,其中Emit生成方法快速调用部分是1、2年前参照卢彦的例子改的(可以单独用到其它场合,不保证没有Bug哦)。脑袋其实不赞成用Emit干活的方式, 我个人同意脑袋的意见; 不过呢, 这个东西也不是完全没用, 放出来抛砖引玉吧。

这个解法的关键代码, 脑袋的“蛮力”解法, 以及这种解法和“蛮力”法之间的区别, 等时间多点一并分析。这个实现和其中的例子都比较草, 基本还是试验级别的,如果有问题可以给我留言。

Update:

做了几个测试, 发现对表达式可能出现的情况估计不足, 很多情况没有处理; 同时取表达式中的值使用了FieldInfo和PropertyInfo的GetValue, 如果执行次数很多, 效率不行(这个问题好解决, 也是用Emit生成快速调用的方法即可)。 大家暂时当例子看看, 我稍后会更新这些代码, 上面的包已经更新了一次, 添加了UnaryExpression作为参数的方法的支持:

jl_Block bundle = MethodCall.Extract(
    () 
=> dc.jl_Blocks.Single(
        (x) 
=> x.ForumID == s.SectionID)
).FromCache().Invoke();

看起来是不是稍微有点变态了? =)  事实上我觉得这样写还是不够爽, 如果变成这样:

jl_Block bundle = Cache(
    () 
=> dc.jl_Blocks.Single(
        (x) 
=> x.ForumID == s.SectionID)
)();

//或者这样

jl_Block bundle 
= Cache(
    () 
=> dc.jl_Blocks.Single        
)((x) 
=> x.ForumID == s.SectionID);

也许比较令人满意, 你觉得上面哪种比较好看呢?大家帮忙想想还有什么比较爽的写法吧。当然, 能不能实现就是另外一码事了 :P 另外, 已经照顾到的情况实际上还是很少的,当前版本肯定还有很多其它问题, 有闲趣的人不妨看看, 和我一起改进。

posted on 2008-06-12 23:54  怪怪  阅读(5307)  评论(19编辑  收藏  举报

导航