【问题标题】:Delphi 10.2 Tokyo - Casting object provided by interfaceDelphi 10.2 Tokyo - 接口提供的铸造对象
【发布时间】:2017-11-14 19:25:01
【问题描述】:

我正在尝试将我的应用程序从 Delphi XE8 转换为 10.2 Tokyo。我遇到了奇怪的运行时异常,它使用了由 interfafce acrocss 包(bpl's)提供的转换对象。当我尝试使用“as”关键字投射对象时,我得到了 运行时出现此异常:

Project Project1.exe 引发异常类 EInvalidCast 并带有消息 '无效的类类型转换'

代码如下:

单独包中的接口 Plugin_interface.bpl :

unit MainIntf;

interface
  Type IMainInft = interface
  ['{FE08C4A2-069C-4B8C-BB1B-445348CAB6A0}']
    function GetForm : TObject;
  end;

implementation

end.

Project1.exe中提供的接口实现:

unit MainImpl;

interface
uses MainIntf;

  Type TMain = class(TInterfacedObject,IInterface,IMainInft)
    function GetForm : TObject;
end;


implementation
uses unit1;

function TMain.GetForm: TObject ;
begin
  result:=Form1; // interafce is implemented on the main form so Form1 is rechable form here
end;


end.

最后在另一个包“plugin.bpl”中,我试图从接口获取对象:

unit Plugin_main;

interface
uses Mainintf, Vcl.Forms;

type TPlugin = class (Tobject)
  IIMyRefernceToMianIntf: IMainInft;
end;

function RegisterPlugin(AMainIntf: IMainInft): TForm ; export;
procedure UnRegisterPlugin; export;

exports
  RegisterPlugin,
  UnRegisterPlugin;

var
 Plugin_obj:  TPlugin;

implementation
uses vcl.Dialogs,System.Classes ;

function RegisterPlugin(AMainIntf: IMainInft): TForm ;
var
 MyForm : TForm ;
begin
  Plugin_obj:=TPlugin.Create;
  Plugin_obj.IIMyRefernceToMianIntf:=AMainIntf;

  if AMainIntf.GetForm is TForm then
    Showmessage ('Great it is a Tform') // will not happen
  else
    Showmessage ('Sorry  it is not Tform'); // will happen 
  if TComponent (AMainIntf.GetForm).Classname='TForm1' then
    Showmessage ('What ?? It is TForm1 decsendant from TForm  so is it TForm after all ?!');  // will happen 
// result:=  AMainIntf.GetForm as TForm  -- This will rise na exception
  result:= TForm( AMainIntf.GetForm)  ; // this will work

end;

procedure UnRegisterPlugin;
begin
  Plugin_obj.Free;
end;
end.

为什么我不能使用“as”和“is”关键字。 只有硬猫会做,但我讨厌这样做。 在 XE8 编译器上,一切都按预期工作 - XE 10.2 tokyo 编译器存在问题

【问题讨论】:

  • 您的项目编译时是否启用了运行时包?这种错误通常意味着 RTL/VCL 库的单个实例未在可执行文件之间共享,从而导致每个可执行文件中的 RTTI 不同。
  • 谢谢 Remy - 就是这样 - 此选项已移至 XE10.2,现在在名为“运行时包”的单独选项页面上称为“与运行时包链接”
  • @jackDph:没有 XE 10.2。它是 Delphi 或 RAD Studio 10.2,看不到 XE。 XE线停在XE8。
  • @RemyLebeau,你真的应该把它变成一个答案,或者 - 更好 - 找到副本并关闭它。

标签: delphi interface delphi-10.2-tokyo


【解决方案1】:

“is”关键字检查实际对象以查看它是否属于您所要求的类型。所以,检查一下:

if AMainIntf.GetForm is TForm then
Showmessage ('Great it is a Tform') // will not happen

不会发生,因为 GetForm 返回 TObject 而不是 TForm。使用“is”检查也意味着您正在检查可铸造性,即使用“as”关键字的能力。由于“is”检查失败,因此该命令也会失败:

result:=  AMainIntf.GetForm as TForm;

您的下一个选择是按照您的方式对 GetForm 进行硬转换:

TForm(AMainIntf.GetForm);

之所以有效,是因为此转换不检查 GetForm 是否属于 TForm 类型。由于您在 TMain 中返回了一个表单,因此您可以放心地选择这种硬选。

话虽如此,但为什么不直接返回TForm 而不是TObject?您是否在返回 TForm 以外的其他类型的其他类中使用 IMainInft

【讨论】:

  • 只要左边的对象在其类层次结构中的某处有TFormas 运算符就可以工作。这里的问题(正如 Remy 在上面的评论中所说)是 BPL 没有与可执行文件共享类型数据,所以有一个不同的TForm
猜你喜欢
  • 2017-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-03
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多