カスタム バリアントでプロパティとメソッドをサポートする
カスタム バリアントの定義:インデックス への移動
バリアントには、プロパティとメソッドを持つものがあります。 たとえば、バリアントの値がインターフェイスの場合、バリアントを使用して、そのインターフェイス上でプロパティの値を読み書きしたり、メソッドを呼び出すことができます。 またたとえカスタム バリアント型がインターフェイスを表すものでなくても、アプリケーションが同様に使えるよう、その型にプロパティやメソッドを持たせたい場合もあるかもしれません。
TInvokeableVariantType を使用する
プロパティやメソッドをサポートさせるには、新しいカスタム バリアント型を有効にするために作成するクラスが、TCustomVariantType から直接派生するのではなく、System.Variants.TInvokeableVariantType の下位クラスでなければなりません。
TInvokeableVariantType は、4 つのメソッドを定義しています:
これらを、カスタム バリアント型で、プロパティやメソッドをサポートするために実装することができます。
たとえば、System.VarConv ユニットは、TInvokeableVariantType を TConvertVariantType の基底クラスとして使用することにより、結果として返されるカスタム バリアントがプロパティをサポートするようにしています。 次の例では、これらプロパティのためのプロパティ取得メソッドを示します:
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])もサポートしている点に注目してください。
同様に、メソッド SetProperty、DoFunction、DoProcedure は十分汎用性が高く、メソッド名を動的に生成したり、変数名やパラメータの型に動的に応答することができます。
TPublishableVariantType を使用する
カスタム バリアント型にオブジェクト インスタンスを使用したデータを格納する場合、 プロパティを実装するさらに簡単な方法があります。ただしこれは、それらプロパティが、バリアントのデータを表すオブジェクトのプロパティでもある場合に限ります。 System.TypInfo.TPublishableVariantType をカスタム バリアント型の基底クラスとして使用している場合、GetInstance メソッドを実装するのみで済み、バリアントのデータを表すオブジェクトの公開プロパティはすべて、自動的にそのカスタム バリアントに対して実装されます。
たとえば、「カスタム バリアント型のデータの保存」で説明したように、TComplexVariantType は、TComplexData のインスタンスを使用して、複素数バリアントのデータを保存します。 TComplexData は、複素数に関する情報を提供する、数多くの公開プロパティを持っています(Real、Imaginary、Radius、Theta、FixedTheta)。 TComplexVariantType は TPublishableVariantType から派生しており、複素数バリアントの TVarData レコード内に格納されている、TComplexData オブジェクト(TypInfo.pas 内)を返す、GetInstance
メソッドを実装します。
function TComplexVariantType.GetInstance(const V: TVarData): TObject;
begin
Result := TComplexVarData(V).VComplex;
end;
TPublishableVariantType は、残りを行います。 GetProperty
および SetProperty
メソッドをオーバーライドし、プロパティ値を取得および設定するために、TComplexData オブジェクトの実行時型情報(RTTI)を使用します。
- メモ: TPublishableVariantType が機能するためには、カスタム バリアントのデータを保有するオブジェクトは、RTTI でコンパイルされなければなりません。 これは、{$M+} コンパイラ指令を使用してコンパイルするか、TPersistent から派生しなければならないことを意味します。