Unterstützung von Eigenschaften und Methoden in selbstdefinierten Variant-Typen

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Benutzerdefinierte Varianten definieren - Index


Einige Variants besitzen Eigenschaften und Methoden. Ist z.B. der Wert eines Variants eine Schnittstelle, können Sie den Variant benutzen, um die Eigenschaften dieser Schnittstelle zu lesen und festzulegen oder die Methoden der Schnittstelle aufzurufen. Auch wenn Ihr selbstdefinierter Variant-Typ keine Schnittstelle darstellt, können Sie ihn mit Eigenschaften und Methoden ausstatten, die eine Anwendung entsprechend benutzen kann.

TInvokeableVariantType benutzen

Zur Unterstützung von Eigenschaften und Methoden muss die von Ihnen erzeugte Klasse, die den neuen selbstdefinierten Variant-Typ aktiviert, von System.Variants.TInvokeableVariantType und nicht direkt von TCustomVariantType abgeleitet sein.

TInvokeableVariantType definiert vier Methoden:

die Sie implementieren können, damit der selbstdefinierte Variant-Typ Eigenschaften und Methoden unterstützt.

Die Unit System.VarConv verwendet beispielsweise TInvokeableVariantType als Basisklasse für TConvertVariantType, sodass die daraus resultierenden selbstdefinierten Variant-Typen Eigenschaften unterstützen. Das folgende Beispiel zeigt den Abruf dieser Eigenschaften:

Delphi:

 function TConvertVariantType.GetProperty(var Dest: TVarData;
 const V: TVarData; const Name: String): Boolean;
 var
 LType: TConvType;
 begin
 // supports...
 //   'Value'
 //   'Type'
 //   'TypeName'
 //   'Family'
 //   'FamilyName'
 //   'As[Type]'
 Result := True;
 if Name = 'VALUE' then
   Variant(Dest) := TConvertVarData(V).VValue
 else if Name = 'TYPE' then
   Variant(Dest) := TConvertVarData(V).VConvType
 else if Name = 'TYPENAME' then
   Variant(Dest) := ConvTypeToDescription(TConvertVarData(V).VConvType)
 else if Name = 'FAMILY' then
   Variant(Dest) := ConvTypeToFamily(TConvertVarData(V).VConvType)
 else if Name = 'FAMILYNAME' then
   Variant(Dest) := ConvFamilyToDescription(ConvTypeToFamily(TConvertVarData(V).VConvType))
 else if System.Copy(Name, 1, 2) = 'AS' then
 begin
   if DescriptionToConvType(ConvTypeToFamily(TConvertVarData(V).VConvType), System.Copy(Name, 3, MaxInt), LType) then
     VarConvertCreateInto(Variant(Dest), Convert(TConvertVarData(V).VValue, TConvertVarData(V).VConvType, LType), LType)
   else
     Result := False;
 end
 else
     Result := False;
 end;

Die Methode GetProperty erkennt anhand des Parameters Name, welche Eigenschaft abgerufen werden soll. Die Information wird dann dem Record TVarData des Variants (V) entnommen und als Variant (Dest) zurückgegeben. Beachten Sie, dass diese Methode Eigenschaften unterstützt, deren Namen, basierend auf dem aktuellen Wert des selbstdefinierten Variants, dynamisch zur Laufzeit generiert werden (As[Type]).

Entsprechend können Sie mit den Methoden SetProperty, DoFunction und DoProcedure Methodennamen dynamisch generieren bzw. auf unterschiedlich viele Parameter oder Parametertypen antworten.

TPublishableVariantType benutzen

Sofern der selbstdefinierte Variant-Typ seine Daten unter Benutzung einer Objektinstanz speichert, gibt es einen einfacheren Weg zur Implementierung von Eigenschaften. Voraussetzung ist, dass diese auch Eigenschaften des Objekts sind, das die Variant-Daten darstellt. Wenn Sie System.TypInfo.TPublishableVariantType als Basisklasse für Ihren selbstdefinierten Variant-Typ benutzen, müssen Sie nur die Methode GetInstance implementieren, und alle veröffentlichten Eigenschaften des Datenobjekts werden automatisch für den selbstdefinierten Variant implementiert.

Wie z. B. im Abschnitt Daten eines selbstdefinierten Variant-Typs speichern gezeigt, speichert TComplexVariantType die Daten eines komplexwertigen Variants unter Benutzung einer Instanz von TComplexData. TComplexData besitzt eine Anzahl veröffentlichter Eigenschaften (Real, Imaginary, Radius, Theta und FixedTheta), die Informationen über den komplexen Wert bereitstellen. TComplexVariantType ist von TPublishableVariantType abgeleitet und implementiert die Methode GetInstance zur Rückgabe des TComplexData-Objekts (in TypInfo.pas), das im TVarData-Record eines komplexwertigen Variants gespeichert ist:

Delphi:

 function TComplexVariantType.GetInstance(const V: TVarData): TObject;
 begin
 Result := TComplexVarData(V).VComplex;
 end;

TPublishableVariantType erledigt das Übrige. TPublishableVariantType überschreibt anschließend die Methoden GetProperty und SetProperty und kann dadurch die RTTI (runtime type information; Typinformation zur Laufzeit) des TComplexData-Objekts nutzen, um Eigenschaftswerte abzufragen und festzulegen.

Hinweis: TPublishableVariantType setzt voraus, das das Objekt, in dem der selbstdefinierte Variant gespeichert ist, mit RTTI compiliert wird. Das heißt, es muss mit der Compiler-Direktive {$M+} compiliert werden oder von TPersistent abstammen.

Siehe auch