如何在没有实例化的情况下确保RTTI可用于某个类?

con*_*tor 7 delphi rtti delphi-xe2

我最近在这个论坛上发布了一个问题,询问有关DXE2可执行文件中缺少RTTI信息的任何建议.

那篇文章是我实际案例的精简版.RRUZ来救援,因此被剥离的版本很快得到了解决.但是,最初的问题仍然存在,所以我现在正在全力发布."主要":

program MissingRTTI;
{$APPTYPE CONSOLE}
uses
  System.SysUtils, RTTI, MyUnit in 'MyUnit.pas', RTTIUtil in 'RTTIUtil.pas';
var
  RHelp:  TRttiHelper;
begin
  RHelp := TRttiHelper.Create();
  if (RHelp.IsTypeFound('MyUnit.TMyClass')) then WriteLn('TMyClass was found.')
  else WriteLn('TMyClass was not found.');
  ReadLn;
  RHelp.Free();
end.
Run Code Online (Sandbox Code Playgroud)

RTTIUtil.pas:

unit RTTIUtil;
interface
uses
  MyUnit;
type
  TRttiHelper = class(TObject)
  public
    function IsTypeFound(TypeName: string) : boolean;
  end;
implementation
uses
  RTTI;
function TRttiHelper.IsTypeFound(TypeName: string): boolean;
var
  rCtx:   TRttiContext;
  rType:  TRttiType;
begin
  Result := false;
  rCtx := TRttiContext.Create();
  rType := rCtx.FindType(TypeName);
  if (rType <> nil) then
    Result := true;
  rCtx.Free();
end;
end.
Run Code Online (Sandbox Code Playgroud)

最后MyUnit.pas:

unit MyUnit;
interface
type
  TMyClass = class(TObject)
  end;
implementation
end.
Run Code Online (Sandbox Code Playgroud)

找不到所需的类型.但是,如果我进行更改TRttiHelper.IsTypeFound以便实例化(并立即释放)实例TMyClass,则会找到该类型.像这样:

function TRttiHelper.IsTypeFound(TypeName: string): boolean;
var
  rCtx:   TRttiContext;
  rType:  TRttiType;
  MyObj:  TMyClass;
begin
  Result := false;
  MyObj:= TMyClass.Create();
  MyObj.Free();
  rCtx := TRttiContext.Create();
  ...
Run Code Online (Sandbox Code Playgroud)

所以我想知道,有没有什么方法可以强制RTTI被发射TMyClass而不实际实例化它?

更新:

在一方面,我可能会提到,如果我尝试使用TRttiType获取TRttiContext.GetType,找到所需的类型.所以有一些RTTI发出.检查通过TRttiType.IsPublic检索的属性TRttiContext.GetType产生一个真值,即检索到的类型是公共的(因此应该可以定位使用TRttiContext.FindType).

Dav*_*nan 16

添加对类的引用,并确保编译器/链接器不能从可执行文件中删除它.

unit MyUnit;

interface

type
  TMyClass = class(TObject)
  end;

implementation 

procedure ForceReferenceToClass(C: TClass);
begin
end;

initialization
  ForceReferenceToClass(TMyClass);

end.
Run Code Online (Sandbox Code Playgroud)

在生产代码中,您可能希望将其放置ForceReferenceToClass在基本单元中,以便可以共享它.声明类的单元的初始化部分是调用的最自然的位置,ForceReferenceToClass因为该单元是自包含的.

关于GetType可以定位类型的观察,调用的行为GetType(TMyClass)会为程序添加对类型的引用.并不是RTTI存在而且FindType无法找到它.相反,包含GetType(TMyClass)将RTTI添加到结果程序中.

  • @conciliator如果你使用[`{$ STRONGLINKTYPES ON}`](http://docwiki.embarcadero.com/RADStudio/en/Strong_link_types_%28Delphi%29)指令,所有类型都将被添加到最终的exe中. (7认同)
  • 但是,如果Embarcadero想出一个强制输出非引用类型的编译器指令,那将会很不错.我甚至有一个名字:{$ FORCERTTI}和随附的快捷方式{$ M!}. (2认同)