如何从TRttiType实例化一个类?

8

我希望能够通过类名字符串创建一个表单,这个问题之前已经被提出, 但是我不想使用GetClass,而是想要使用Delphi的新RTTI功能。

通过这段代码,我已经得到了一个TRttiType,但是我不知道如何实例化它。

var
  f:TFormBase;
  ctx:TRttiContext;
  lType:TRttiType;
begin
  ctx := TRttiContext.Create;
  for lType in ctx.GetTypes do
  begin
    if lType.Name = 'TFormFormulirPendaftaran' then
    begin
      //how to instantiate lType here?
      Break;
    end;
  end;
end;

我也尝试过lType.NewInstance,但没有成功。

2个回答

11
你必须将 TRttiType 转换为 TRttiInstanceType 类,然后使用 GetMethod 函数调用构造函数。请尝试此示例。
var
  ctx:TRttiContext;
  lType:TRttiType;
  t : TRttiInstanceType;
  f : TValue;
begin
  ctx := TRttiContext.Create;
  lType:= ctx.FindType('UnitName.TFormFormulirPendaftaran');
  if lType<>nil then
  begin
    t:=lType.AsInstance;
    f:= t.GetMethod('Create').Invoke(t.MetaclassType,[nil]);
    t.GetMethod('Show').Invoke(f,[]);
  end;
end;

一旦您实例化了Form对象,就不需要再使用RTTI来调用其Show()方法了。只需正常调用即可:f.Show; - Remy Lebeau
@RemyLebeau,对于此示例 f 是一个 TValue,当然 OP 可以引入一个 TForm 帮助变量或者只需将 TValue 强制转换为 Tform,如下所示 TForm(f.AsObject).Show; - RRUZ
抱歉,我没有注意到 f 是一个 TValue,当我看到 Niyoko 的代码时才发现的。 - Remy Lebeau

4

你应该使用TRttiContext.FindType()方法来替代手动循环遍历TRttiContext.GetTypes()列表,例如:

lType := ctx.FindType('ScopeName.UnitName.TFormFormulirPendaftaran');
if lType <> nil then
begin
  ...
end;

无论如何,一旦您已经找到所需类类型的TRttiType,就可以像这样实例化它:

type
  TFormBaseClass = class of TFormBase;

f := TFormBaseClass(GetTypeData(lType.Handle)^.ClassType).Create(TheDesiredOwnerHere);

如果 TFormBase 是从 TForm 派生的话,可以使用以下代码:
f := TFormClass(GetTypeData(lType.Handle)^.ClassType).Create(TheDesiredOwnerHere);

如果 TFormBase 是从 TCustomForm 派生的,则可以使用以下代码:
f := TCustomFormClass(GetTypeData(lType.Handle)^.ClassType).Create(TheDesiredOwnerHere);

更新: 或者像 @RRUZ 展示的那样做。这更加面向 TRttiType,而且不依赖于使用较旧的 TypInfo 单元中的函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接