Как сохранить ссылку TRttiMethod на переменную? - PullRequest
0 голосов
/ 30 апреля 2020

Я хочу сохранить метод конструктора класса, которого я не знаю, во время компиляции, поэтому я могу вызвать его позже, чтобы создать объект указанного класса. Если возможно, я не хочу использовать TClass.Create, так как он не вызывает конструктор по умолчанию для объекта.

Вот код для воспроизведения проблемы:

uses
  System.SysUtils,
  Rtti;

type
  TClass1 = class
    constructor Create(pInt: Integer);
  end;

constructor TClass1.Create(pInt: Integer);
begin
end;

procedure PrintMethod(FMethod: TRttiMethod);
begin
  writeln(Format('Address: %d, Value Adress: %d, Method: %s,  Handle: %d, Params: %d, ClassName: %s',
      [Integer(FMethod), Integer(Addr(FMethod)), FMethod.Name, Integer(FMethod.Handle), Length(FMethod.GetParameters), FMethod.Parent.AsInstance.MetaclassType.ClassName]));
end;

function FindCreateMethod(pClass: TClass): TRttiMethod;
var
  rContext: TRttiContext;
  rType: TRttiType;
  FMethods: TArray<TRttiMethod>;
  I: Integer;
begin
  rContext:= TRttiContext.Create;
  rType:= rContext.GetType(pClass);
  FMethods:= rType.GetMethods;
  for I:= Low(FMethods) to High(FMethods) do
    if SameText('Create', FMethods[I].Name) then
    begin
      Result:= FMethods[I];
      Break;
    end;
  PrintMethod(Result);
end;

var
  FMethod: TRttiMethod;
begin
  FMethod:= FindCreateMethod(TClass1);//Prints: Address: 39354896, Value Adress: 1703672, Method: Create,  Handle: 4654648, Params: 1, ClassName: TClass1
  // Outside the scope of the function FindCreateMethod GetParameters does not work for FMethod
  PrintMethod(FMethod); //Prints: Address: 39354896, Value Adress: 1703740, Method: Create,  Handle: 4654648, Params: 0, ClassName: TClass1

  with TRttiContext.Create do
    GetType(TClass1).GetMethods; // After GetMethods call the value of FMethod changes

  PrintMethod(FMethod); //Prints: Address: 39354896, Value Adress: 1703740, Method: Destroy,  Handle: 4200544, Params: 0, ClassName: TObject
  readln;
end.

Что здесь происходит? Очевидно, каждый раз, когда вызывается GetMethods(), он воссоздает экземпляры TRTTIMethod для типа. Есть ли надежный способ хранения экземпляра TRttiMethod без необходимости l oop через все методы каждый раз?

Я использую Delphi Berlin 10.1 update 2.

Решено : Благодаря комментарию @RemyLebeau проблема была решена с помощью глобального экземпляра TRTTiContext. По-видимому, в TRTTIContext есть информация, которая подсчитывается ссылками, и, поскольку единственным экземпляром TRTTIcontext был тот, который я создавал внутри функции FindCreateMethod, когда он вышел из области видимости, счетчик ссылок перешел на 0, а экземпляр TRTTIMethods был потерял.

1 Ответ

1 голос
/ 30 апреля 2020

Благодаря комментарию @RemyLebeau проблема была решена с помощью глобального экземпляра TRTTiContext. По-видимому, в TRTTIContext есть информация, которая подсчитывается по ссылкам, и, поскольку единственным экземпляром TRTTIcontext был тот, который я создавал внутри функции FindCreateMethod, когда он вышел из области видимости, счетчик ссылок перешел в 0, а экземпляр TRTTIMethods был потерян.

...