Я хочу сохранить метод конструктора класса, которого я не знаю, во время компиляции, поэтому я могу вызвать его позже, чтобы создать объект указанного класса. Если возможно, я не хочу использовать 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 был потерял.