2010-06-18 5 views
14

Comme nous l'avons tous connu, lorsque l'on appelle un constructeur d'une classe comme ceci:Comment créer une instance d'objet avec RTTI dans Delphi 2010?

instance := TSomeClass.Create; 

Le compilateur Delphi ne fait les choses suivantes:

  1. Appelez la méthode NewInstance statique pour allouer de la mémoire et initialiser la disposition de la mémoire.
  2. Appelez la méthode constructeur pour effectuer l'initialisation de l'appel classe
  3. la méthode AfterConstruction

Il est simple et facile à comprendre. mais je ne suis pas très sûr comment le compilateur gérer les exceptions dans la deuxième et la troisième étape.

Il semble qu'il n'y ait pas de manière explicite de créer une instance en utilisant une méthode de constructeur RTTI dans D2010. J'ai donc écrit une fonction simple dans Spring Framework for Delphi pour reproduire le processus de création.

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; 

Je pense que ce n'est peut-être pas 100% vrai. alors s'il vous plaît montrez-moi le chemin. Merci!

Répondre

18

L'appel du constructeur et le passage de la classe à l'argument Self (par opposition à une instance) construira correctement la classe. Le processus de construction comprend les NewInstance, AfterConstruction etc. que vous faites manuellement ici: ce n'est pas nécessaire.

Cela devrait être suffisant:

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

Une bizarrerie de Delphes comment il permet les constructeurs à appeler sur les instances ainsi que des cours. Cette fonctionnalité est utilisée comme une sorte de "placement nouveau" (en C++) pour la construction de formulaire, de sorte que la variable de formulaire global (par exemple Form1 pour le premier formulaire) est affectée au moment où le constructeur OnCreate est invoqué. Ainsi, votre code ne déclenche pas d'exception. Mais il est plus normal de passer la classe plutôt que l'instance comme argument Self.

+0

Merci beaucoup! J'ai finalement eu pourquoi il y a une surcharge de l'Invoke avec un paramètre de classe. –

+0

@Paul: Cette surcharge peut également être utilisée pour appeler les méthodes ** class **. –

+0

Oui. Mais j'étais confus par le nom du paramètre. (Instance: TClass ...) –

Questions connexes