2010-06-18 10 views
14

Come tutti conosciuti, quando chiamiamo un costruttore di una classe come questa:Come creare un'istanza di oggetto con RTTI in Delphi 2010?

instance := TSomeClass.Create; 

Il compilatore Delphi effettivamente fare le seguenti cose:

  1. Chiamare il NewInstance metodo statico per allocare la memoria e inizializza il layout di memoria.
  2. Chiamare il metodo di costruzione per eseguire l'inizializzazione della classe
  3. chiamata al metodo AfterConstruction

E 'semplice e facile da capire. ma non sono molto sicuro di come il compilatore gestisca le eccezioni nel secondo e nel terzo passo.

Sembra che non ci sia un modo esplicito per creare un'istanza utilizzando un metodo di costruzione RTTI in D2010. così ho scritto una semplice funzione in Spring Framework per Delphi per riprodurre il processo della creazione.

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; 

Mi sembra che non sia al 100% giusto. quindi per favore mostrami la via Grazie!

risposta

18

Il richiamo del costruttore e il passaggio della classe come argomento Self (a differenza di un'istanza) costruiscono correttamente la classe. Il processo di costruzione include NewInstance, AfterConstruction ecc. Che stai facendo manualmente qui: non è necessario.

Questo dovrebbe essere sufficiente:

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

Una curiosità di Delphi è così che permette costruttori di essere chiamato su istanze nonché per le classi. Questa funzione viene utilizzata come una sorta di "posizionamento nuovo" (in terminologia C++) per la costruzione di moduli, in modo che la variabile globale del modulo (ad esempio Form1 per impostazione predefinita per il primo modulo) venga assegnata al momento in cui viene richiamato il costruttore OnCreate. Pertanto, il tuo codice non genera un'eccezione. Ma è più normale passare la classe piuttosto che l'istanza come argomento Self.

+0

Grazie mille! Ho finalmente capito perché c'è un sovraccarico di Invoke con un parametro di classe. –

+0

@Paul: questo sovraccarico può anche essere usato per chiamare i metodi ** class **. –

+0

Sì. Ma ero confuso dal nome del parametro. (Istanza: TClass ...) –

Problemi correlati