カスタム バリアントでプロパティとメソッドをサポートする

提供: Appmethod Topics
移動先: 案内検索

カスタム バリアントの定義:インデックス への移動


バリアントには、プロパティとメソッドを持つものがあります。 たとえば、バリアントの値がインターフェイスの場合、バリアントを使用して、そのインターフェイス上でプロパティの値を読み書きしたり、メソッドを呼び出すことができます。 またたとえカスタム バリアント型がインターフェイスを表すものでなくても、アプリケーションが同様に使えるよう、その型にプロパティやメソッドを持たせたい場合もあるかもしれません。

TInvokeableVariantType を使用する

プロパティやメソッドをサポートさせるには、新しいカスタム バリアント型を有効にするために作成するクラスが、TCustomVariantType から直接派生するのではなく、System.Variants.TInvokeableVariantType の下位クラスでなければなりません。


TInvokeableVariantType は、4 つのメソッドを定義しています:

これらを、カスタム バリアント型で、プロパティやメソッドをサポートするために実装することができます。

たとえば、System.VarConv ユニットは、TInvokeableVariantTypeTConvertVariantType の基底クラスとして使用することにより、結果として返されるカスタム バリアントがプロパティをサポートするようにしています。 次の例では、これらプロパティのためのプロパティ取得メソッドを示します:

Object Pascal:
 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;

GetProperty メソッドは、Name パラメータをチェックし、どのプロパティがほしいかを判断します。 その後、 Variant (V)の TVarData レコードから情報を取得し、それを Variant (Dest)として返します。 このメソッドは、カスタム バリアントの現在の値を基に、実行時に動的に名前が生成されるプロパティ(As[Type])もサポートしている点に注目してください。

同様に、メソッド SetPropertyDoFunctionDoProcedure は十分汎用性が高く、メソッド名を動的に生成したり、変数名やパラメータの型に動的に応答することができます。

TPublishableVariantType を使用する

カスタム バリアント型にオブジェクト インスタンスを使用したデータを格納する場合、 プロパティを実装するさらに簡単な方法があります。ただしこれは、それらプロパティが、バリアントのデータを表すオブジェクトのプロパティでもある場合に限ります。 System.TypInfo.TPublishableVariantType をカスタム バリアント型の基底クラスとして使用している場合、GetInstance メソッドを実装するのみで済み、バリアントのデータを表すオブジェクトの公開プロパティはすべて、自動的にそのカスタム バリアントに対して実装されます。

たとえば、「カスタム バリアント型のデータの保存」で説明したように、TComplexVariantType は、TComplexData のインスタンスを使用して、複素数バリアントのデータを保存します。 TComplexData は、複素数に関する情報を提供する、数多くの公開プロパティを持っています(Real、Imaginary、Radius、Theta、FixedTheta)。 TComplexVariantTypeTPublishableVariantType から派生しており、複素数バリアントの TVarData レコード内に格納されている、TComplexData オブジェクト(TypInfo.pas 内)を返す、GetInstance メソッドを実装します。

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

TPublishableVariantType は、残りを行います。 GetProperty および SetProperty メソッドをオーバーライドし、プロパティ値を取得および設定するために、TComplexData オブジェクトの実行時型情報(RTTI)を使用します。

メモ: TPublishableVariantType が機能するためには、カスタム バリアントのデータを保有するオブジェクトは、RTTI でコンパイルされなければなりません。 これは、{$M+} コンパイラ指令を使用してコンパイルするか、TPersistent から派生しなければならないことを意味します。

関連項目