Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Получить информацию о методах

Delphi , Компоненты и Классы , Свойства и События



Автор: Xavier Pacheco

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, DBClient, MidasCon, MConnect;

type

  TMainForm = class(TForm)
    lbSampMethods: TListBox;
    lbMethodInfo: TMemo;
    lblBasicMethodInfo: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure lbSampMethodsClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation
uses TypInfo, DBTables, Provider;

{$R *.DFM}

type
  // It is necessary to redefine this record as it is commented out in
  // typinfo.pas.

  PParamRecord = ^TParamRecord;
  TParamRecord = record
    Flags: TParamFlags;
    ParamName: ShortString;
    TypeName: ShortString;
  end;

procedure GetBaseMethodInfo(ATypeInfo: PTypeInfo; AStrings: TStrings);
{ This method obtains some basic RTTI data from the TTypeInfo and adds that
  information to the AStrings parameter. }
var
  MethodTypeData: PTypeData;
  EnumName: string;
begin
  MethodTypeData := GetTypeData(ATypeInfo);
  with AStrings do
  begin
    Add(Format('Class Name:     %s', [ATypeInfo^.Name]));
    EnumName := GetEnumName(TypeInfo(TTypeKind), Integer(ATypeInfo^.Kind));
    Add(Format('Kind:           %s', [EnumName]));
    Add(Format('Num Parameters: %d', [MethodTypeData.ParamCount]));
  end;
end;

procedure GetMethodDefinition(ATypeInfo: PTypeInfo; AStrings: TStrings);
{ This method retrieves the property info on a method pointer. We use this
  information to recunstruct the method definition. }
var
  MethodTypeData: PTypeData;
  MethodDefine: string;
  ParamRecord: PParamRecord;
  TypeStr: ^ShortString;
  ReturnStr: ^ShortString;
  i: integer;
begin
  MethodTypeData := GetTypeData(ATypeInfo);

  // Determine the type of method
  case MethodTypeData.MethodKind of
    mkProcedure: MethodDefine := 'procedure ';
    mkFunction: MethodDefine := 'function ';
    mkConstructor: MethodDefine := 'constructor ';
    mkDestructor: MethodDefine := 'destructor ';
    mkClassProcedure: MethodDefine := 'class procedure ';
    mkClassFunction: MethodDefine := 'class function ';
  end;

  // point to the first parameter
  ParamRecord := @MethodTypeData.ParamList;
  i := 1; // first parameter

  // loop through the method's parameters and add them to the string list as
  // they would be normally defined.
  while i <= MethodTypeData.ParamCount do
  begin
    if i = 1 then
      MethodDefine := MethodDefine + '(';

    if pfVar in ParamRecord.Flags then
      MethodDefine := MethodDefine + ('var ');
    if pfconst in ParamRecord.Flags then
      MethodDefine := MethodDefine + ('const ');
    if pfArray in ParamRecord.Flags then
      MethodDefine := MethodDefine + ('array of ');
    //  we won't do anything for the pfAddress but know that the Self parameter
    //  gets passed with this flag set.
    {
        if pfAddress in ParamRecord.Flags then
          MethodDefine := MethodDefine+('*address* ');
    }
    if pfout in ParamRecord.Flags then
      MethodDefine := MethodDefine + ('out ');

    // Use pointer arithmetic to get the type string for the parameter.
    TypeStr := Pointer(Integer(@ParamRecord^.ParamName) +
      Length(ParamRecord^.ParamName) + 1);

    MethodDefine := Format('%s%s: %s', [MethodDefine, ParamRecord^.ParamName,
      TypeStr^]);

    inc(i); // Increment the counter.

    // Go the next parameter. Notice that use of pointer arithmetic to
    // get to the appropriate location of the next parameter.
    ParamRecord := PParamRecord(Integer(ParamRecord) + SizeOf(TParamFlags) +
      (Length(ParamRecord^.ParamName) + 1) + (Length(TypeStr^) + 1));

    // if there are still parameters then setup
    if i <= MethodTypeData.ParamCount then
    begin
      MethodDefine := MethodDefine + '; ';
    end
    else
      MethodDefine := MethodDefine + ')';
  end;

  // If the method type is a function, it has a return value. This is also
  // placed in the method definition string. The return value will be at the
  // location following the last parameter.
  if MethodTypeData.MethodKind = mkFunction then
  begin
    ReturnStr := Pointer(ParamRecord);
    MethodDefine := Format('%s: %s;', [MethodDefine, ReturnStr^])
  end
  else
    MethodDefine := MethodDefine + ';';

  // finally, add the string to the listbox.
  with AStrings do
  begin
    Add(MethodDefine)
  end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  { Add some method types to the list box. Also, store the pointer to the RTTI
    data in listbox's Objects array }
  with lbSampMethods.Items do
  begin
    AddObject('TNotifyEvent', TypeInfo(TNotifyEvent));
    AddObject('TMouseEvent', TypeInfo(TMouseEvent));
    AddObject('TBDECallBackEvent', TypeInfo(TBDECallBackEvent));
    AddObject('TDataRequestEvent', TypeInfo(TDataRequestEvent));
    AddObject('TGetModuleProc', TypeInfo(TGetModuleProc));
    AddObject('TReaderError', TypeInfo(TReaderError));
  end;
end;

procedure TMainForm.lbSampMethodsClick(Sender: TObject);
begin
  lbMethodInfo.Lines.Clear;
  with lbSampMethods do
  begin
    GetBaseMethodInfo(PTypeInfo(Items.Objects[ItemIndex]), lbMethodInfo.Lines);
    GetMethodDefinition(PTypeInfo(Items.Objects[ItemIndex]),
      lbMethodInfo.Lines);
  end;
end;

end.

Here's the translation of the content into Russian:

Класс формы

Класс TMainForm - это наследник класса TForm, который является стандартным классом для форм в Delphi. Он имеет два списка (lbSampMethods и lbMethodInfo) и один компонент мемо (lblBasicMethodInfo) для отображения информации.

Процедура GetBaseMethodInfo

Эта процедура принимает указатель на PTypeInfo (который указывает на данные RTTI) и объект TStrings (список строк) в качестве входных параметров. Она получает основные данные RTTI из указателя на PTypeInfo, такие как имя класса, тип и количество параметров, и добавляет их в объект TStrings.

Процедура GetMethodDefinition

Эта процедура принимает указатель на PTypeInfo (который указывает на данные RTTI) и объект TStrings (список строк) в качестве входных параметров. Она получает информацию о свойствах метода и реконструирует строку определения метода, включая имя метода, параметры и тип возвращаемого значения.

Процедура FormCreate

Эта процедура вызывается при создании формы. Она добавляет некоторые типы методов в список (lbSampMethods) и хранит указатель на данные RTTI в массиве объектов списка.

Процедура lbSampMethodsClick

Эта процедура вызывается, когда пользователь кликнул по элементу в списке (lbSampMethods). Она очищает компонент мемо (lblBasicMethodInfo) и получает основные данные RTTI для выбранного метода с помощью процедуры GetBaseMethodInfo. Затем она получает информацию о свойствах метода с помощью процедуры GetMethodDefinition и добавляет ее в компонент мемо.

Альтернативное решение

Одно из альтернативных решений может быть использование встроенных в Delphi функций RTTI, таких как класс RTTIInfo, который предоставляет более удобный способ доступа к данным RTTI. Кроме того, вы можете использовать функцию GetTypeInfo() для получения указателя на PTypeInfo для заданного типа.

Вот пример, как можно модифицировать код с помощью RTTIInfo:

procedure TMainForm.GetMethodDefinition(ATypeInfo: PTypeInfo; AStrings: TStrings);
begin
  with RTTIInfo.Create(ATypeInfo) do
  begin
    // Получение строки определения метода
    AStrings.Add(Format('%s %s', [MethodName, Parameters]));
  end;
end;

В этом примере класс RTTIInfo используется для создания экземпляра, который обертывает указатель на PTypeInfo. Свойство MethodName возвращает имя метода, а свойство Parameters возвращает строковое представление параметров метода.

Методы получения информации о методах в Delphi с использованием RTTI-технологии описаны в статье автора Xavier Pacheco.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Свойства и События ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-05-01 12:22:47/0.0039489269256592/0