[英]Component is specific class - does not work in BPL structure
I am upgrading Delphi software from Delphi 6 (2001) to Delphi 11 Alexandria.我正在将 Delphi 软件从 Delphi 6 (2001) 升级到 Delphi 11 Alexandria。
This software consists of many BPL's, but this code is not working properly.该软件包含许多 BPL,但此代码无法正常工作。 The is command is not returning True, when checking if the component from a BPL is an TIBQuery - although it really is.
当检查来自 BPL 的组件是否是 TIBQuery 时, is 命令没有返回 True,尽管它确实是。
procedure LoadDLLAndPassDatabaseConnection(const DLLName: string);
var
PackageHandle: HMODULE;
ServiceModule: TMyServiceModule;
I: Integer;
Component: TComponent;
begin
PackageHandle := LoadPackage(PChar(DLLName));
ServiceModule := TMyServiceModule(GetProcAddress(hInst,'GetServiceModule'));
if Assigned(ServiceModule) then
begin
for I:=0 to ServiceModule.ComponentCount - 1 do
begin
Component := ServiceModule.Components[I];
// This component is declared in another bpl.
// It really is an TIBQuery, but the following if never returns True...
// (Evaluating Component.ClassName results in 'TIBQuery')
if Component is TIBQuery then
begin
// this is never executed...
TIBQuery(Component).Database := GetDatabase;
end;
end;
end;
end;
I already considered to compare classnames, but this does not work for descendants.我已经考虑过比较类名,但这不适用于后代。 And we tried toggling project options such as "Emit runtime type information", but that's not making any difference.
我们尝试切换项目选项,例如“Emit runtime type information”,但这没有任何区别。
How to get this working?如何让这个工作?
Thank you!谢谢!
The is
operator does not work across BPLs (DLLs) for the following reason: is
运算符不能跨 BPL (DLL) 工作,原因如下:
Now: the class name
is the same for the two modules, but the RTTI, used by the is
operator to check equality, are different , so the operator returns FALSE !现在:两个模块的
class name
相同,但是is
运算符用于检查相等性的 RTTI不同,因此运算符返回FALSE !
Solution: check equality againts class name.解决方案:检查 class 名称是否相等。
As Antonio Petricca wrote (thank you,), it's not possible to use the is
operator.正如 Antonio Petricca 所写(谢谢),不可能使用
is
运算符。 I now have implemented this by comparing (descendant) class names - I want to share the code:我现在通过比较(后代)class 名称来实现这一点 - 我想分享代码:
function IsSameClassOrAncestor(const ClazzToCheck: TClass; const Clazz: TClass): Boolean;
begin
Result := SameText(ClazzToCheck.ClassName, Clazz.ClassName);
if not Result and not SameText(ClazzToCheck.ClassName, 'TObject') then
begin
Result := IsSameClassOrAncestor(ClazzToCheck.ClassParent, Clazz);
end;
end;
This way, I can check this as follows:这样,我可以检查如下:
if IsSameClassOrAncestor(Component, TIBQuery)
begin
// The code is now executed correctly, also for descendants
TIBQuery(Component).Database := GetDatabase;
end;
I found this somewhere, but it seems to contradict Antionio's answer a bit.我在某个地方找到了这个,但它似乎与 Antionio 的回答有点矛盾。
When you use packages, there is only ever one copy of any unit in memory.
使用包时,memory 中的任何单元都只有一个副本。 One copy of Forms, one copy of SysUtils, one copy of System (well, most of it), one copy of StdCtrls, etc. All class-related operations, such as the "is" and "as" operators, rely on class references.
Forms 一份,SysUtils 一份,System 一份(嗯,大部分),StdCtrls 一份等。所有与类相关的操作,例如“is”和“as”运算符,都依赖于 class参考。 Class references are actually just addresses.
Class 引用实际上只是地址。 They point to definitions for the layouts of the classes' internals.
它们指向类内部布局的定义。 (They point to what's called the virtual-method table, the VMT.) Two classes are the same if they point to the same VMT -- if the addresses are equal.
(它们指向所谓的虚拟方法表,即 VMT。)如果两个类指向同一个 VMT——如果地址相等,则它们是相同的。 When you have a class defined in the EXE's copy of StdCtrls and the same class defined in a DLL's copy of StdCtrls, those classes will really have different addresses.
当您在 EXE 的 StdCtrls 副本中定义了 class 并且在 DLL 的 StdCtrls 副本中定义了相同的 class 时,这些类实际上将具有不同的地址。 The "is" and "as" operators won't work with cross-module clases.
“is”和“as”运算符不适用于跨模块类。 But when you use packages, there is only one copy of the class, kept in vcl70.bpl, so all modules that reference that package will share a single class definition.
但是,当您使用包时,只有一份 class 副本保存在 vcl70.bpl 中,因此所有引用该 package 的模块将共享一个 class 定义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.