2008-12-14 7 views

Répondre

6

Ceci est juste une opinion, d'après mon expérience avec ce que les variantes peuvent et ne peuvent pas faire. Si vous y ajoutez un objet COM, celui-ci sera stocké en tant que référence IDispatch. Ainsi, tous les appels de méthode ou propriétés auxquels vous accédez sur cet objet seront convertis en un code qui recherche le DISPID interne de la méthode/property, un tableau avec des arguments de méthode sera construit et la méthode sera invoquée via l'interface IDispatch. En d'autres termes, IDispatch est géré pour vous, comme vous le feriez normalement, mais c'est fait automatiquement par le compilateur. Toutefois, pour les objets Delphi normaux, les choses deviennent plus difficiles. Vous pouvez utiliser RTTI pour rechercher et appeler des méthodes et des propriétés publiées, mais c'est à peu près tout. Si vous avez le nom d'une méthode non-publiée, non-virtuelle, Delphi ne peut pas trouver la bonne adresse pour votre méthode.

En d'autres termes, tout ce que vous seriez en mesure de faire serait de simplement détenir l'objet, vous ne seriez pas en mesure de l'utiliser. Peut-être qu'ils pourraient ajouter un soutien pour simplement le libérer, mais encore une fois, ce serait probablement le cas.

Je sais pertinemment que si vous implémentez IDispatch correctement, vous pouvez stocker en toute sécurité et utiliser l'objet via une variante. J'ai une classe qui peut être utilisée comme classe de base pour les objets Delphi sur lesquels vous voulez faire cela. Il expose automatiquement les méthodes/propriétés publiées et vous pouvez en ajouter d'autres si vous le souhaitez via certains appels de méthodes protégées. S'il y a un intérêt pour une telle classe, je peux la placer quelque part.

Mais encore une fois, ceci est via IDispatch, et il utilise les méthodes publiées, le reste est du code manuel, donc le support pour les variantes doit être intégré dans vos objets, par vous.

C'est pourquoi je pense qu'ils ont juste dit: Cela va simplement générer des plaintes, que nous pouvons tenir un objet mais c'est inutile.

Mais c'est juste mes pensées. Peut-être que quelqu'un d'officiel a une bien meilleure réponse.

+4

Vous êtes à peu près droit. Vous devriez également mentionner les classes TCustomVariantType et TInvokeableVariantType. Ces classes montrent toutes les choses qu'une classe devrait faire pour pouvoir être * utilisé * (pas seulement stocké) dans un Variant, sans nécessairement implémenter IDispatch. –

+0

+1 à Rob: TCustomVariantType et TInvokeableVariantType sont assez puissants. Certaines pénalités de performance, mais qui [peuvent être contournées avec un peu de piratage de bas niveau] (http://blog.synopse.info/post/2011/07/01/Faster-variant-late-binding). –

24

Vous pouvez certainement stocker un objet à l'intérieur d'une variable Variant - il suffit de le transformer en un NativeUInt. Un objet est juste un pointeur, de toute façon.

obj := TObject.Create; 
v := NativeUInt(obj); 
obj := TSomeObject(NativeUInt(v)); 
6

j'avais utilisé des variantes à tenir des objets dans le passé en utilisant les variantes internes, le code est quelque chose comme ceci:

var 
    MyObject: TMyObject; 
    Value: Variant; 
begin 
    MyObject:= TMyObject.Create; 
    TVarData(Value).VType:= VarByRef; 
    TVarData(Value).VPointer:= MyObject; 
+1

Notez que vous trichez. VarByRef est un * drapeau * destiné à modifier le champ de type sous-jacent. Votre code indique que la variable est * vide *, mais elle est vide par référence. –

+0

Hmmm? Rob, cela signifie que varIsEmpty reviendrait True ??? –

+1

Conceptuellement c'est OK je pense; logiquement, une référence non typée à un emplacement est équivalente à un pointeur non typé, c'est-à-dire void * dans C ou Pointer dans Delphi. –

Questions connexes