前两天一直昏昏沉沉,提不起精神,今天才有点起色
今天仔细看jgtm2004给我发的link
我对AOP不了解,对模式也不是很熟悉,两周后空下来了,仔细去学习学习
我想到一种方法,不过我没有验证过可不可行,只是突然想到而已
如下。
基本原理:
现在Runtime越来越流行,是不是可以搭建一个Runtime,我们通过这Runtime来调用某些类?
首先声明一个 delegate
delegate RTMCallFunctionEventHandler;
在RTM类里面定义俩个事件,
public class RTM
{
public event RTMCallFunctionEventHandler Calling;
public event RTMCallFunctionEventHandler Called;
public void Call(Type functionName, Paremeters paremeters)
{
if (Calling;!= null)
Calling;(sender,e);
调用
if (Called;!= null)
Called;(sender,e);
}
}
在其他类中订阅者这两个事件,进行处理。
调用某个类的方法时要通过RTM
public class Calculator
{
public int Add(int x, int y) { return x + y; }
}
public class myClass
{
public void CallAdd()
{
int result;
result = RTM.Call(functionName := Calculator.Add; paremeters := paremeters(1,2));
}
}
打印 | 张贴于 2004-02-05 10:30:00 | Tag:Dot Net

留言反馈
按你这个要求的话,看来这个周末还是写不不来啊——还要老少皆宜……看来我得先做个读者调查啦!:)
@iamcrc:
开眼界!谢谢你给我们的信息!有精力我会好好研究一下的。总的来说,AOP在.NET中的情况也是差不多,也是主要就这么几种机制。而我目前主要关注的是在不利用第三方产品的前提下仅利用.NET/CLR的机制来实现基本的也是最有意义的AOP编程——当然我也想揭示一些尚存的问题,更希望微软能够重视AOP对于.NET世界的重要意义。
@jjx:
的确,MTS应该说是实现AOP概念的第一个实例了!这还是得益于COM世界基于纯抽象接口的设计——正如文章第一部分所说,这是应用DECORATOR模式的重要基础。而对于Java社区而言,当年它高举OOP大旗,现在看来又要引领AOP了。不过也好,.NET正好可以在它演变的过程中取其精华、去其糟粕——等到Aspect.NET出现的时候,相信该是AOP进入成熟阶段的标志了。
总之,关注技术的发展,更要关注技术发展能给我们带来的实际好处。而我写文章的目的,就是希望更多的人能够了解这些好处并将其运用起来,并从中获取更大的价值。:)
在java世界中的AOP framework我知道的有四个:
AspectJ、AspectWerkz、nanning、JBoss AOP,其中
AspectJ正如JGTM大侠说说,利用编译期代码缝合。
AspectWerkz利用了class loader(bootstrap class loader除外)在加载类时,从配置文件中读取必要的信息,修改类的行为(称为weave);
nanning是基于java.lang.reflect.Proxy 的思路实现的,利用动态代理把调用切换到事先定义好的Interceptor中。
而JBoss AOP还可以支持元数据,元数据能够起到C#中属性类似的功能(很有意思吧:))。而JBoss AOP的元数据支持是通过xDoclet来实现。
可以看出,Java中的AOP,目前也分为运行时动态加载、静态缝合和加载虚拟机时动态加载 三个方向。
其实jdk下一版本的,好像一直有在考虑参考C#中面向属性开发的技术。
ps:以上言论引诉了不少我的好友axing给我的讲解:)
你说的利用.Net Remoting方法实现偶也隐约猜出了个大概。
CLR本身为了实现远程调用,利用了Proxy模式,在本地创建了一个proxy对象,这个proxy对象在调用远程的realproxy对象执行方法时,会在前面后面插入自己的操作...
前阵子看过在Java中利用proxy模式实现远程调用的一篇东西,正好还有些印象,Java中好像是通过让proxy对象继承一个SessionHandler接口,Java Runtime在这个接口上做了一些手脚,于是proxy对象可以在调用realproxy对象前后做些事情。
快快把后篇写完了发出来,申明偶对COM、ATL不熟悉的说,所以拜托尽量写得深入浅出、通俗易懂、老少皆宜...
你说的这个功能CLR已经有了(实际上CLR就是为这个目的设计的,这部分架构即所谓的.NET Remoting Infrastructure)。比如下面的代码:
MyObject o = new MyObject();
o.Call();
如果MyObject是一个配置好的远程对象的话,那么CLR必须要拦截o.Call()方法调用并将其转发到远程服务器上。我所提到的实现AOP的方法也是基于这个技术,只不过最终调用还是转发到本地对象——但是中间已经经过了我们设置的处理不同aspect的代码。因此说,你想做的这么一个runtime(看到RTM总让我以为是released-to-manufactory:)似乎意义不大(虽然你不改变server的代码,但是client的代码会被搞乱)。
看来以后我写文章还是应该一气呵成,不能只说半拉,不然太容易引起误解咯。:)
所以progame说jgtm的aop比起java下的aop差得太多了,这是仁者见仁,智者见智,况且用不同的语言来实现本来就有差异,我们应该将焦点集中于差异在那里,怎么改进设计,还有什么其他的方式,不同方式的优劣分析等等
对于语言一些具体特性的争论,没有必要下定论说好还是不好,语言是死的,对我们应用的人来说重要的是如何灵活运用,趋利避害。
@JGTM'2004
我所说的RTM不是指CLR那样的,大概是一个framework,他会对方法的调用加以解析,在不改变原有server代码的基础上,添加新的功能.
是不是就Java下面的AOP才是真正的AOP?听你这么评价问题,不知道的人以为AOP是由老大你定义的呢!AspectJ是很酷,我也很欣赏它的创意和机制,但这并不意味着它就是完美的AOP——这是由它的实现原理所决定的(编译期代码缝合)。
同理,我也不能说目前.NET/CLR提供的各种机制就能够实现所谓真正的AOP(我一直认为“真正的”或说理想中的AOP还是可能要靠新的语言特性和编译器支持才能够实现,就像C++的template或者C#中的generic一样,包括AspectJ——它不是也有自己的编译器吗)——其实真不真正又有什么意义呢?我们需要的是利用技术解决问题,而不是找个话茬儿做些无聊的评论!
如果老兄有好的见地,不妨指教一二:什么才算是真正的AOP?需要那些机制才能够实现真正的AOP?在.NET中如何借助AOP的思想和CLR的机制解决一些OOP不能很好解决的问题?
另外关于动态属性,我不得不再跟你叫板:我知道你说的实际上是custom attribute。这东西可不是动态的,它是静态的,所以适用于相对代码而言是静态的那些特征描述场合——如线程相依性、唯一标识等等。这些东西不需要也不允许在代码之外和运行期间动态改变,因此静态的自定义属性是再合适不过的了。反之,如果你需要动态性,那么可以使用外部配置信息来改变程序的运行行为(如ORM中的mapping schema)。然而,两者结合起来更是相得益彰啊!我可以使用静态的custom attribute静态的描述代码的默认行为,同时引入外部配置信息允许override一些需要灵活性的动态配置信息……无论是custom attribute还是外部配置文件也好,无非是为程序提供一些环境参数信息从而产生不同的执行逻辑而已,没什么本质不同(就好比一些存在光盘上的数据和一些存在硬盘上的数据一样:数据可死可活,程序(员)更是如此!!)。这么好的开发特性你却总是嗤之以鼻,有一说一,我真觉得你已经有些“审美疲劳”喽……
所以这里拜托你在探讨问题的时候把相关概念、原理、应用场合等等都搞清楚,不要总是断章取义或是片面的评论问题。我们讨论的问题都是牵扯到很多方面的,不是一个概念就可以为其定性的。所以,如果你只用这些无关痛痒的东西为一件事物定性,只能说明你的知识面还太单薄了——我真的很奇怪,为什么你总是跟custom attribute过不去,这东西和我们讨论的话题有直接关系吗?它不就是一些与代码绑定的静态元数据吗?你干吗老是大惊小怪的用它混淆视听?能不能把注意力放到问题本身提出你的见解?——最后一次就“动态属性”给你摆事实讲道理了噢!谢谢你虚心接受我的意见!:)
如com+的transcation和nunit的test
但这样的aop比起java下的aop差得太多了
因为我还是那样的理解
动态属性依然是类的一部分
这也是我当初为什么反对使用属性做为o/r mapper
所以这样的aop也不是真正的aop
本文的最终目的是给大家一个新的思路来解决文章中引出的问题,也就是说利用CLR自身提供的机制为已有对象扩充功能,而不会搞乱客户代码和对象代码(不过还是需要改变和添加一些声明)。比如已有的代码如下:
客户代码:
ICalculator calculator = new Calculator();
Console.WriteLine(calculator.Add(3, 5));
对象代码:
public class Calculator: ICalculator
{
public int Add(int x, int y) { return x+y; }
}
如果我需要在执行的时候能够得到客户代码对Calculator方法的调用日志,我只需要给Calculator添加[Logging]属性即可——对象已有的方法实现不受任何影响、调用代码也不受任何影响——这正是AOP技术的目的。
如果有人以前实践过类似的机制,也希望你能把一些想法与大家分享一下。:)
在文章下篇完成之前,感兴趣的朋友们可以顺着文章第一部分结尾处的提示先对CLR中的相关机制作些了解。第二篇中会有一些新东西与大家分享——第一篇主要是引出问题,而不是完美的解决问题(虽然很多朋友给我写信说学到很多东西,可我要写得其实还没写出来呢……:)