delphi – 发布的接口属性bug和解决方法
我写了一组通过已发布的接口属性相互链接的组件。它们已注册并安装在设计包中。
使用已发布的接口属性在Delphi中并不常见,因此,不出所料,似乎没有那么好。 当组件位于同一表单上时,它工作正常,但是不同表单上组件之间的接口属性链接会导致问题。 与对象链接到另一个表单上的组件不同,IDE似乎无法识别接口链接。我的意思是最好的一个例子,当你有两个窗体在IDE中打开,并有组件之间的链接,然后试图切换到文本形式视图(Alt F12)将导致IDE正确地抱怨: 模块“UnitXXX.pas”具有打开的后代或链接的模块。无法关闭。 但是如果属性是一个接口,这不会发生,而是发生了什么,是链接被切断(这是最好的情况下,当你使用通知机制来清除引用,否则你留下一个无效的指针) 另一个问题,可能是由于同一个错误的结果,当你在IDE中打开一个项目时,窗体将重新打开的顺序是未定义的,因此IDE可以尝试打开一个包含组件的组件的组件,另一种形式,但是其他形式没有重新创建。所以这有效地导致AV或切断链接。 回到90年代,当我使用数据集和数据源我记得类似的问题之间的链接消失,所以这有点类似。 作为临时解决方法,我添加了重复的已发布属性,对于每个接口属性,我添加了另一个声明为TComponent。这使得Delphi意识到在表单之间有一个链接,但是是一个丑陋的解决方法,至少说。 所以我不知道有没有什么我可以做的来解决这个问题?这是一个IDE错误,可能无法直接修复,但也许我可以重写一些东西,否则钩到流机制,以更有效地解决这个错误。 我从来没有这么深入流机制,但我怀疑Fixup机制应该处理这一点。有一个csFixups TComponentState所以我希望一个解决方法是可能的。 编辑:使用D2007。 更新: 新更新的可重复示例已上传到http://www.filedropper.com/fixupbugproject2 添加了属性ComponentReference:TComponent,以便于比较和跟踪接口与组件流。 我把问题缩小到了我的深度以外的汇编水平。 在过程GlobalFixupReferences在类单位它调用: (GetOrdProp(FInstance,FPropInfo)<> 0) 最终执行: function TInterfacedComponent.GetInterfaceReference: IInterface; begin // uncomment the code bellow to avoid exception { if (csLoading in ComponentState) and (FInterfaceReference = nil) then // leave result unassigned to avoid exception else } result := FInterfaceReference; // <----- Exception happens here end; 正如你可以从注释中看到的,我发现避免异常的唯一方法是保留结果未分配,但打破了功能,因为上面的比较GlobalFixupReferences失败,由于GetOrdProp<> 0,它断开了链接。 跟踪更准确的位置的异常是在 procedure _IntfCopy(var Dest:IInterface; const Source:IInterface);在系统单元中 这一行特别引发读地址0x80000000 { Now we're into the less common cases. } @@NilSource: MOV ECX,[EAX] // get current value 所以,为什么MOV失败,什么错误ECX或EAX我不知道。 解决方法
总之,只有具有getter方法的已发布接口属性才会出现问题,并且属性指向另一个表单/模块上的组件(并且该表单/模块尚未重新创建)。在这种情况下,恢复形式DFM导致AV。
我很确定错误是在GetOrdProp的ASM代码,但它超出了我的能力,所以 或者,您可以将属性声明为TComponent而不是interface,然后写入TComponentProperty后代,重写ComponentMayBeSetTo以过滤不支持所需接口的组件。当然,使用RegisterPropertyEditor注册它 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |