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

发布于 2024-09-06 18:53:35 字数 1196 浏览 7 评论 0原文

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

instance := TSomeClass.Create;

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

  1. 调用静态NewInstance方法 分配内存并初始化 内存布局。
  2. 调用构造函数方法 执行类的初始化
  3. 调用 AfterConstruction 方法

简单易懂。但我不太确定编译器如何处理第二步和第三步中的异常。

在 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%正确。所以请给我指路。谢谢!

As we all known, when we call a constructor of a class like this:

instance := TSomeClass.Create;

The Delphi compiler actually do the following things:

  1. Call the static NewInstance method
    to allocate memory and initialize
    the memory layout.
  2. Call the constructor method to
    perform the initialization of the class
  3. Call the AfterConstruction method

It's simple and easy to understand. but I'm not very sure how the compiler handle exceptions in the second and the third step.

It seems there are no explicit way to create an instance using a RTTI constructor method in D2010. so I wrote a simple function in the Spring Framework for Delphi to reproduce the process of the creation.

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;

I feel it maybe not 100% right. so please show me the way. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浸婚纱 2024-09-13 18:53:35

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

这应该足够了:

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

Delphi 的一个奇怪之处是它允许在实例和类上调用构造函数。此功能用作表单构建的一种“新放置”(C++ 术语),以便全局表单变量(例如,第一个表单默认为 Form1)在创建时被分配。 OnCreate 构造函数被调用。因此,您的代码不会引发异常。但将类而不是实例作为 Self 参数传递更为正常。

Invoking the constructor and passing the class as the Self argument (as opposed to an instance) will correctly construct the class. The process of constructing includes the NewInstance, AfterConstruction etc. that you are manually doing here: it's not necessary.

This ought to be sufficient:

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

An oddity of Delphi is how it permits constructors to be called on instances as well as classes. This feature is used as a kind of "placement new" (in C++ terminology) for form construction, so that the global form variable (e.g. Form1 by default for the first form) is assigned at the time that the OnCreate constructor gets invoked. Thus, your code doesn't raise an exception. But it is more normal to pass the class rather than the instance as the Self argument.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文