Custom Variant Wrapper for TDataset - Part 5

In Part 4 I showed you how to get and set dynamic properties of our custom variant.  In this part I will show how custom variants can be cast to and from other data types.

There are two TCustomVariantType methods that must be overridden to allow a custom variant to be cast to and from other data types.  Cast and CastTo are used to cast another data type into a custom variant and to cast a custom variant into another data type, respectively.  Failure to override these two methods will result in ‘Invalid variant type conversion’ errors if an attempt is made to cast the custom variant to a different data type.

Since our TDataset wrapper variant simply holds a reference to a TDataset, it doesn’t make much sense to cast it to a different value.  So, by way of illustration, we will consider a variant that holds a measurement.  The data structure for this variant was introduced in Part 1 as follows:


TMeasurementData = packed record
VType: TVarType;
VUnits: Char;
Reserved1: Char;
Reserved2, Reserved3: Word;
VMeasurement: Double;
end;

The Cast method accepts two arguments; Dest which is an instance of our custom variant which will be updated to hold the value of Source which is a variant holding the new value.  We will create a Cast method that will cast a string of the form measurement:units to our custom variant type.  The method looks like this:


procedure TMeasurmentVariant.Cast(var Dest: TVarData; const Source: TVarData);
var
colon: Integer;
s: String;
begin
case Source.VType of
varString:
begin
s := VarDataToStr(Source);
colon := Pos(':', s);
TMeasureData(Dest).VType := VarType;
TMeasureData(Dest).VUnits := Copy(s, colon + 1, 1);
TMeasureDara(Dest).VMeasurement := StrToFloat(Copy(s, 1, colon - 1));
end;
else
raise Exception.Create('Invalid typecast');
end;
end;

The CastTo accepts three agruments; Dest which is a variant that will receive our custom variant cast as a string in the same format as that accepted by Cast, Source which is an instance of our custom variant and AVarType which is the data type that our custom variant is to be cast into.  The method looks like this:


procedure TMeasurementVariant.CastTo(var Dest: TVarData; const Source: TVarData; const AVarType: TVarType);
var
v: Variant;
begin
case AVarType of
varString:
begin
v := Format('%f:%s', [TMeasurementData(Source).VMeasurement,
String(TMeasurementData(Source).VUnits]));
Variant(Dest) := v;
end;
else
raise Exception.Create('Invalid typecast');
end;
end;

Leave a Reply