DELPHI.NET 关于RTTI/反射的问题(100)

  • 主题发起人 主题发起人 龙丹
  • 开始时间 开始时间

龙丹

Unregistered / Unconfirmed
GUEST, unregistred user!
在DELPHI中,象这样的属性 property Items[Index: Integer]: TItemObj read GetItem write SetItem;是不能在Published段声明的,因此也就没有RTTI。为了在运行时通过RTTI来访问Items的各个成员,在Published声明属性: property Item0: TItemObj Index 0 read GetItem write SetItem;这样可以访问到Items[0]。只要 PropInfo := GetPropInfo(Obj,'Item0'); PropInfo.Index := 5;通过PropInfo就可以访问到Items[5]。在DELPHI2009.NET中,TPropInfo和Win32版不同了,改用.NET反射了。我现在的问题是,没找到能够执行象 PropInfo.Index := 5 这样功能的地方,也没有找到其它实现上述目的的办法。怎么办呢?请大家帮忙出出主意。
 
顶贴加瞎掰吧:1.在DELPHI2009.NET中,TPropInfo和Win32版不同了,改用.NET反射了。既然使用.Net了,就应该用.Net的一套思路来考虑问题。不能用Delphi for Win32来考虑了。2.Delphi的Property属性应该是在编译器一级支持的(瞎猜的)。所以PropInfo.Index := 5感觉上像是移动指针的操作(还是瞎猜的)。3.这个问题原来的处理方法就是个变通方法(绑定编译器的)。所以要换到.Net应该有一定的难度。我想:是不是可以直接读内存来实现;或者用对象的序列化来实现(即把对象序列化后再读取序列化后的内容)?4.这些都是瞎猜或者乱想。其他不说啦,顶贴吧。
 
咱也瞎掰吧:总的来说,用.NET就用.NET思路是没错的。但是呢,DELPHI.NET的一个重要特性,就是让咱能够用既有的技巧来开发.NET应用(CodeGear自己说的哦),大多数情况下也确实如此,而且不仅仅是技巧,还有实实在在的代码积累,当然也有许多受.NET制约而不得不改的东西(以后再说)。就这RTTI来说,DELPHI也尽量保持了与以前版本的兼容,但还是把最基础的结构(如TPropInfo)换成了.NET的类(MemberInfo),我认为在这一点上处理是欠妥的,RTTI和反射本来就两套东西,保持RTTI基础结构不变,以前依赖RTTI的应用就可以直接使用(如DevExpress 的 属性编辑器),新的程序也不必考虑RTTI而直接使用反射就行了,而现在这样给老程序的迁移凭添许多麻烦,又没有给新程序带来什么额外的好处。(DevExpress V40说是支持D2009,也仅仅是WIN32而以,.NET下编译都过不了,尽管代码中用了许多编译指令来区别CLR与否。)当然,这只是个人看法+牢sao瘙而已,没办法了。另外,PropInfo.Index 是 RTTI 中调用属性访问器携带的参数,所以改变它就能访问不同索引的属性。原来的处理方法是依赖RTTI的,现在依然是,只是现在的RTTI变味了,和以前的不兼容了,于是咱就有了这个问题了。那怎么办呢?请大家帮忙出出主意啊。
 
看来确实没人来,那我继续瞎掰吧:1.笨方法也是方法,实在不行,就用property Item0: TItemObj Index 0 read GetItem0 write SetItem0;property Item1: TItemObj Index 1 read GetItem1 write SetItem1;.......property ItemN: TItemObj Index N read GetItemN write SetItemN;2.没有通读过Delphi.Net的代码,也不知道源代码里有没有你这样类似的情况,所以也不好说。3.还有,实在不行,直接Post给CodeGear,让大牛给你支招吧。
 
呵呵,之前我也确实用过这个办法,在列表项比较少的类中还能凑合用,而且GetItem和SetItem也只需要一对,有Index参数嘛。DELPHI.NET也没问题。只是这个办法确实有点笨,既然是用列表项,项数通常是不确定的,如果我发布了10个属性,哪怕实际上只有1项,程序也会列出10项,而另一方面呢,如果项比较多,10以后的仍然无法访问到。
 
简单的方法,还是换会到delphi 7版本上吧. [:)] delphi 2009 还没有用过,也不熟悉.帮顶一下.
 
对我的笨方法再加点补充吧。1.为你的类添加一个基础类,例如:TMyObject<-TMyPropObject2.自己写段程序生成TMyPropObject的单元代码Unit,这个Unit基本上只处理Property Item0..Property ItemN,说白啦,就是生成10000个或者是100000000个都只点个按钮生成Unit然后编译,其它让编译器去搞定。3.这个笨方法会让一群人笑话的。哈哈哈。。。
 
不知道搂主是不是非要在.net框架下实现原来的rtti才行.我觉得搂主需要实现的功能用.net的反射机制肯定是完全可以实现的啊!虽然我不知道.net的反射怎么实现,但是反射的能力是,只要你知道对象的类的名字(字符串类型变量) 你就可以得到这个对象的方法(方法对象),并调用对象的方法(反射调用)。不过我真的不懂.net.如果是java,用反射的话这个问题就不是问题,rtti也根本没有用处了。
 
索引器,getter,setter
 
看来又无解啊
 
根据猜测,要在这种情况下RTTI,一般是为了在运行时能够持久化对象数据。因为没办法在Published声明,那么就表明无法GetPropList得到属性指针,那么想访问Items各个成员就无从谈起了。如果是为了在基类中持久化子类数据(子类属性个数未知)的话,估计property Item0:那是个唯一办法了--而这时Published声明的含义就变成了“需要持久化的数据”的同义词如果猜测得对,那么问题就变成了“如何在vcl.net下如何在基类编写持久化代码,同时能对子类起作用”,这时就要解决两个问题:1.要知道一共有多少个属性 -- 反射应该能解决问题2.要知道哪些属性需要被搞 -- delphi.win32是通过Published声明,运行时GetPropList, .net下,可以在基类中用一个数组保存属性名列表~~~~--反正,编译器机制完全不一样,所以这种语言一级的特性还是区别对待为好的。如果没猜对,就当我路过~~
 
非常高兴还有朋友关心这个问题其实说RTTI也好反射也好,其应用还是比较广的,比如szf所说的持久化(包括ORM),还有诸如属性编辑器、通过脚本操纵对象、编写通用框架等等,很多,所以我不主张把这个问题局限到具体应用上(其实就持久化而言,我有自己完整的处理机制)。还有一些朋友问我,为什么不用反射呢?其实很简单,这个问题源自于对现有基础平台的迁移。个人认为对已经完成的并且正常工作的工件,再用采用另外一种方式来重做一遍意义不大(对个人尤其是对社会都不能带来什么价值,有时间有精力的话我更愿意做一些有意义的事情),基于这种考虑,我认为DELPHI VCL for .NET确实是非常不错的架构,原来的许多代码都可以直接迁移过来,然而在RTTI的处理上似乎并不妥当,受此影响,依赖于RTTI的产品一般都不能顺利迁移过来(DevExpress Vertical Grid 中的属性编辑器就是一个显著的案例)
 
记得很多年前编程的人都知道“DOS未公开的调用”这么个词。升级到win后,很多dos程序都不能跑了,这个引起很多人很大意见,但历史的长河还是滚滚向前啊...把这个思路套在现在的软件开发上的框架和运行时变化上,也是行得通的。
 
回到问题上来,还是看看有没有什么解决办法吧
 
你老兄没有明白我的意思。我是想说,有些技术未公开,也没进入技术文档,那么厂商就没有理由一定要兼容下去的,既然是未公开的调用,那么在后续版本中不可用也是无可厚非的。比如说TypInfo单元的GetPropInfop这个方法多次overload后,最终是用汇编实现--这就说明了,这些单元是跟编译器版本密切相关的。不光GetPropInfo方法,TypInfo单元中,多个方法最终都是用汇编实现,这就说明了VCL.win32的RTTI是跟编译器紧密结合的,而不是跟Delphi语言的紧密结合的,VCL.net是用什么编译器我不知道,不过估计跟dcc32.exe的关系没有以前密切是肯定的。所以,原来那种hack写法在新平台下实现不了,一点都不奇怪。不过对老兄你的执着精神表示佩服,祝你好运,我已经订阅此邮件,有了解决方法也不忘了也指点一下小弟我:)
 
多人接受答案了。
 
后退
顶部