如何在Delphi 2010中使用RTTI创建对象实例?
众所周知,当我们像这样调用类的构造函数时:
instance := TSomeClass.Create;
Delphi编译器实际上做了以下几件事:
- 调用静态NewInstance方法 分配内存并初始化 内存布局。
- 调用构造函数方法 执行类的初始化
- 调用 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:
- Call the static NewInstance method
to allocate memory and initialize
the memory layout. - Call the constructor method to
perform the initialization of the class - 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
调用构造函数并将类作为
Self
参数(而不是实例)传递将正确构造该类。构建的过程包括NewInstance
、AfterConstruction
等,您在这里手动执行:这不是必需的。这应该足够了:
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 theNewInstance
,AfterConstruction
etc. that you are manually doing here: it's not necessary.This ought to be sufficient:
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 theOnCreate
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 theSelf
argument.