Как создать экземпляр объекта с 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.