Как создать экземпляр объекта с RTTI в Delphi 2010? - PullRequest
14 голосов
/ 18 июня 2010

Как все мы знаем, когда мы вызываем конструктор класса, подобного этому:

instance := TSomeClass.Create;

Компилятор Delphi фактически выполняет следующие действия:

  1. вызов статического метода NewInstance. выделить память и инициализировать макет памяти.
  2. вызов метода конструктора для выполнить инициализацию класса
  3. Вызов метода AfterConstruction

Это просто и легко понять. но я не совсем уверен, как компилятор обрабатывает исключения на втором и третьем шаге.

Кажется, в D2010 нет явного способа создания экземпляра с использованием метода конструктора RTTI. поэтому я написал простую функцию в 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 Ответ

18 голосов
/ 18 июня 2010

Вызов конструктора и передача класса в качестве аргумента Self (в отличие от экземпляра) позволит правильно построить класс.Процесс построения включает в себя NewInstance, AfterConstruction и т. Д., Которые вы здесь делаете вручную: это не обязательно.

Этого должно быть достаточно:

Result := constructorMethod.Invoke(instanceType.MetaclassType, arguments);

СтранностьDelphi позволяет конструкторам вызываться как для экземпляров, так и для классов.Эта функция используется как своего рода «размещение нового» (в терминологии C ++) для построения формы, поэтому глобальная переменная формы (например, Form1 по умолчанию для первой формы) назначается в то время, когда конструктор OnCreateвызывается.Таким образом, ваш код не вызывает исключения.Но более нормально передавать класс, а не экземпляр в качестве аргумента Self.

...