如何在Delphi 2010中使用RTTI创建对象实例?

时间:2010-06-18 10:18:56

标签: delphi delphi-2010 rtti

众所周知,当我们调用这样一个类的构造函数时:

instance := TSomeClass.Create;

Delphi编译器实际上做了以下事情:

  1. 调用静态NewInstance方法 分配内存并初始化 内存布局。
  2. 调用构造函数方法 执行类的初始化
  3. 调用AfterConstruction方法
  4. 简单易懂。但我不太确定编译器如何处理第二步和第三步中的异常。

    似乎没有明确的方法在D2010中使用RTTI构造函数方法创建实例。所以我在Spring Framework for 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 个答案:

答案 0 :(得分:18)

调用构造函数并将类作为Self参数(而不是实例)传递将正确构造类。构建过程包括您在此处手动执行的NewInstanceAfterConstruction等等:没有必要。

这应该足够了:

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

Delphi的一个奇怪之处在于它如何允许在实例和类上调用构造函数。此功能用作表单构造的一种“放置新”(在C ++术语中),因此在{{{{{{{{{{{{{{ 1}}构造函数被调用。因此,您的代码不会引发异常。但是将类而不是实例作为Form1参数传递更为正常。