2013-02-07 8 views
8

Voglio creare un modulo dato il suo nome di classe come una stringa, which has been asked about before, ma invece di chiamare GetClass, voglio utilizzare la nuova funzione RTTI di Delphi.Come creare un'istanza di una classe dal suo TRttiType?

Con questo codice, ho uno TRttiType, ma non so come istanziarlo.

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; 

Ho anche provato lType.NewInstance senza fortuna.

risposta

9

È necessario eseguire il cast della classe TRttiType nella classe TRttiInstanceType e quindi richiamare la funzione di costruzione utilizzando la funzione GetMethod.

Prova questo campione

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

Dopo aver istanziato l'oggetto Form, non è più necessario utilizzare RTTI per chiamare il suo metodo 'Show()'. Chiamalo normalmente: 'f.Show;' –

+0

@RemyLebeau, su questo esempio f è un TValue, ovviamente l'OP può introdurre una variabile helper di TForm o semplicemente lanciare il TValue su un Tform come in questo modo 'TForm (f.AsObject) .Show; ' – RRUZ

+0

Scusa, non ho notato che' f' era un 'TValue', stavo guardando il codice di Niyoko quando l'ho visto. –

4

Si dovrebbe utilizzare il metodo TRttiContext.FindType() invece di loop manualmente attraverso se la lista TRttiContext.GetTypes(), ad esempio:

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

Ma in entrambi i casi, una volta individuato il TRttiType per il tipo di classe desiderato, puoi istanziarlo in questo modo:

type 
    TFormBaseClass = class of TFormBase; 

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

O questo, se TFormBase è derivato da TForm:

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

O questo, se TFormBase è derivato da TCustomForm:

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

Aggiornamento: Oppure, fare come @RRUZ mostrato. Questo è più orientato a TRttiType e non si basa sull'uso di funzioni dalla precedente unità TypInfo.