RAD Studio |  |

Supporting Properties and Methods in Custom Variants
Using TInvokeableVariantType | Using TPublishableVariantType | See Also
Collapse All

Some variants have properties and methods. For example, when the value of a variant is an interface, you can use the variant to read or write the values of properties on that interface and call its methods. Even if your custom variant type does not represent an interface, you may want to give it properties and methods that an application can use in the same way.

Using TInvokeableVariantType

To provide support for properties and methods, the class you create to enable the new custom variant type should descend from TInvokeableVariantType instead of directly from TCustomVariantType.

TInvokeableVariantType defines four methods:

- DoFunction
- DoProcedure
- GetProperty
- SetProperty

that you can implement to support properties and methods on your custom variant type.

For example, the VarConv unit uses TInvokeableVariantType as the base class for TConvertVariantType so that the resulting custom variants can support properties. The following example shows the property getter for these properties:

Copy Code

    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;

The GetProperty method checks the Name parameter to determine what property is wanted. It then retrieves the information from the TVarData record of the Variant (V), and returns it as a Variant (Dest). Note that this method supports properties whose names are dynamically generated at runtime (As[Type]), based on the current value of the custom variant.

Similarly, the SetProperty, DoFunction, and DoProcedure methods are sufficiently generic that you can dynamically generate method names, or respond to variable numbers and types of parameters.

Using TPublishableVariantType

If the custom variant type stores its data using an object instance, then there is an easier way to implement properties, as long as they are also properties of the object that represents the variant's data. If you use TPublishableVariantType as the base class for your custom variant type, then you need only implement the GetInstance method, and all the published properties of the object that represents the variant's data are automatically implemented for the custom variants.

For example, as was seen in Storing a custom variant type's data, TComplexVariantType stores the data of a complex-valued variant using an instance of TComplexData. TComplexData has a number of published properties (Real, Imaginary, Radius, Theta, and FixedTheta), that provide information about the complex value. TComplexVariantType descends from TPublishableVariantType, and implements the GetInstance method to return the TComplexData object (in TypInfo.pas) that is stored in a complex-valued variant's TVarData record:

Copy Code

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

TPublishableVariantType does the rest. It overrides the GetProperty and SetProperty methods to use the runtime type information (RTTI) of the TComplexData object for getting and setting property values.

Note: For TPublishableVariantType to work, the object that holds the custom variant's data must be compiled with RTTI. This means it must be compiled using the {$M+} compiler directive, or descend from TPersistent.
See Also

Storing a Custom Variant Type's Data

Creating a Class to Enable the Custom Variant Type

Writing Utilities to Work with a Custom Variant Type

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!