2013-02-07 78 views
8

我想創建一個表單,其類名爲字符串which has been asked about before,但我不想調用GetClass,我想使用Delphi的新RTTI功能。使用此代碼,我有TRttiType,但我不知道如何實例化它。如何從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沒有運氣。

回答

9

您必須將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; 
+0

一旦你實例化了Form對象,你就不需要再使用RTTI來調用它的Show()方法。正常地調用它:'f.Show;' –

+0

@RemyLebeau,在這個示例f上是一個TValue,當然OP可以引入一個TForm輔助變量或只是將TValue強制轉換爲Tform,就像'TForm(f.AsObject) .Show;' – RRUZ

+0

對不起,我沒有注意到'f'是一個'TValue',我看到Niyoko的代碼。 –

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); 

還是這個,如果TFormBaseTForm得出:

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

還是這個,如果TFormBaseTCustomForm得出:

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

更新:或者說,它像@RRUZ顯示。這是更多TRttiType爲導向,並不依賴於使用舊的TypInfo單位的功能。