Как создать экземпляр объекта с RTTI в Delphi 2010?
Как мы все знаем, когда мы вызываем конструктор такого класса:
instance := TSomeClass.Create;
Компилятор Delphi действительно выполняет следующие действия:
- Вызов статического метода NewInstance
для выделения памяти и инициализации
расположение памяти.
- Вызов метода конструктора для
выполнить инициализацию класса
- Вызов метода AfterConstruction
Это просто и легко понять. но я не очень уверен, как компилятор обрабатывает исключения во втором и третьем шагах.
Кажется, нет явного способа создания экземпляра с использованием метода конструктора RTTI в D2010. поэтому я написал простую функцию в Spring Framework для Delphi для воспроизведения процесса создания.
class function TActivator.CreateInstance(instanceType: TRttiInstanceType;
constructorMethod: TRttiMethod; const arguments: array of TValue): TObject;
var
classType: TClass;
begin
TArgument.CheckNotNull(instanceType, 'instanceType');
TArgument.CheckNotNull(constructorMethod, 'constructorMethod');
classType := instanceType.MetaclassType;
Result := classType.NewInstance;
try
constructorMethod.Invoke(Result, arguments);
except
on Exception do
begin
if Result is TInterfacedObject then
begin
Dec(TInterfacedObjectHack(Result).FRefCount);
end;
Result.Free;
raise;
end;
end;
try
Result.AfterConstruction;
except
on Exception do
begin
Result.Free;
raise;
end;
end;
end;
Я чувствую, что это может быть не на 100% правильно. поэтому, пожалуйста, покажи мне путь. Спасибо!
Ответы
Ответ 1
Вызов конструктора и передача класса в качестве аргумента Self
(в отличие от экземпляра) корректно построит класс. Процесс построения включает в себя NewInstance
, AfterConstruction
и т.д., Которые вы здесь делаете вручную: это необязательно.
Это должно быть достаточно:
Result := constructorMethod.Invoke(instanceType.MetaclassType, arguments);
Нечетность Delphi заключается в том, как она позволяет конструкторам вызываться как для экземпляров, так и для классов. Эта функция используется как своего рода "размещение нового" (в терминологии С++) для построения формы, так что глобальная переменная формы (например, Form1
по умолчанию для первой формы) назначается в то время, когда конструктор OnCreate
вызывается. Таким образом, ваш код не вызывает исключения. Но более естественно передавать класс, а не экземпляр, как аргумент Self
.