【问题标题】:ClassInfo function in Delphi 7Delphi 7 中的 ClassInfo 函数
【发布时间】:2023-03-25 09:35:02
【问题描述】:

当我在 Delphi 7 中定义这样的类时:

  TPerson = class(TObject)
  private
    FLName: string;
    FFName: string;
    FAge: integer;
    FBDate: TDate;
  public
  published
    property FName: string read FFName write FFName;
    property LName: string read FLName write FLName;
    property Age: integer read FAge write FAge;
    property BDate: TDate read FBDate write FBDate;
  end;

procedure ListComponentProperties(AObject: TObject; Strings: TStrings);
var
  Count, Size, I: Integer;
  List: PPropList;
  PropInfo: PPropInfo;
  PropValue: string;
begin
  Count := GetPropList(AObject.ClassInfo, tkAny, List);
  Size  := Count * SizeOf(Pointer);
  GetMem(List, Size);
  try
    Count := GetPropList(AObject.ClassInfo, tkAny, List);
    for I := 0 to Count - 1 do
    begin
      PropInfo := List^[I];
      PropValue := VarToStr(GetPropValue(AObject, PropInfo^.Name));
    end;
  finally
    FreeMem(List);
  end;
end;

并且我想通过 ListComponentProperties 获取其已发布属性的列表,将显示错误消息。该错误与以下命令和 AObject.ClassInfo 有关:

Count := GetPropList(AObject.ClassInfo, tkAny, List);

任何帮助将不胜感激。

【问题讨论】:

  • 以后当您提出与错误消息相关的问题时,请在您的问题中包含错误消息,并逐字引用。

标签: delphi delphi-7 rtti


【解决方案1】:

您必须为该类型启用 RTTI。默认情况下未启用。像这样声明类型:

type
  {$M+}
  TPerson = class(TObject)
  ....
  end;
  {$M-}

您对GetPropList 的初次调用也是错误的。它必须是:

Count := GetPropList(AObject.ClassInfo, tkAny, nil);

如果您启用警告,编译器会告诉您您正在传递一个未初始化的变量。

我没有再检查过你的代码。可能会有更多错误。

【讨论】:

  • 谢谢,是否可以一劳永逸地在应用程序级别启用 RTTI?
  • 没有。最好的方法是从 $M+ 类型派生
【解决方案2】:

除了使用$M 编译器指令之外,您还可以从启用了 RTTI 信息的任何类派生您的类。

其中一个类是TPersistent,它应该用作任何需要具有分配和流功能的类的基类。

TPersistent 封装了常见的行为 可以分配给其他对象的所有对象,并且可以 在表单文件(.xfm 或 .dfm)中读取和写入它们的属性 文件)。

不要创建 TPersistent 的实例。使用 TPersistent 作为 声明不是组件的对象时的基类,但 需要保存到流或将其属性分配给 其他对象。

实际上,这意味着如果您想使用 TPerson 类作为某些组件的已发布属性,这些组件可以通过 Object Inspector 在 IDE 中编辑并流式传输到表单文件 (.dfm),您的类必须具有 TPersistent 作为其类层次结构中的祖先。

type
  TPersonComponent = class(TComponent)
  protected
    FPerson: TPerson;
    procedure SetPerson(AValue: TPerson);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Person: TPerson read FPerson write SetPerson;
  end;

constructor TPersonComponent.Create(AOwner: TComponent);
begin
  inherited;
  FPerson := TPerson.Create;
end;

destructor TPersonComponent.Destroy;
begin
  FPerson.Free;
  inherited;
end;

procedure TPersonComponent.SetPerson(AValue: TPerson);
begin
  FPerson.Assign(AValue);
end;

如果您在上例中使用声明为TPerson = class(TObject) 的类,则在对象检查器中编辑TPersonComponent 时,其属性(即使已发布并打开RTTI 信息)将不会保存到.dfm 文件中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多