Podemos incrementar nossa class helper, Tdataset, for in, acrescentando mais um elemento: as variants.

Vamos usar variants para incrementar nossos for in, para isso vamos acrescentar recursos como métodos e propriedades,e invés de nosso enumerador retornar um índice ele retornará uma variant assim podemos acessar suas propriedades, usando da seguinte maneira:


data.First_Name
Com a class helper será a responsável de retornar a nossa variant adequada, para isso precisamos modificar para GetCurrent retornar uma variante invés o número do registro.

Além disso, precisamos criar uma class que herde TInvokeableVariantType e sobrescrever alguns métodos.


type
  TVarDataRecordType = class(TInvokeableVariantType)
  public
    procedure Clear(var V: TVarData); override;
    procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean); override;
    function GetProperty(var Dest: TVarData; const V: TVarData; const Name: string): Boolean; override;
    function SetProperty(const V: TVarData; const Name: string; const Value: TVarData): Boolean; override;
  end;
Para que economizamos memória, vamos criar somente uma instância depois criarmos record para armazenar os dados da variante.


type
  TVarDataRecordData = packed record
    VType: TVarType;
    Reserved1, Reserved2, Reserved3: Word;
    DataSet: TDataSet;
    Reserved4: LongInt;
  end;
Este nosso record é uma forma simplificada da TVarData record declarado em system.pas como só temos que armazenar uma referência ao conjunto de dados podemos manter da forma mais simples.

Agora precisaremos de uma variável global para uma instância de TVarDataRecordType, é uma função retornando o VarType dessa instância e outra função a criação de uma variant desse tipo.


var
  VarDataRecordType: TVarDataRecordType = nil;

function VarDataRecord: TVarType;
begin
  result := VarDataRecordType.VarType;
end;

function VarDataRecordCreate(ADataSet: TDataSet): Variant;
begin
  VarClear(result);
  TVarDataRecordData(result).VType := VarDataRecord;
  TVarDataRecordData(result).DataSet := ADataSet;
end;
Os métodos clean e copy TVarDataRecordType são bem simples só precisa chamar os métodos TCustomVariantType. Porém agora nos métodos GetProperty e SetProperty são aonde as coisas são feitos.


function TVarDataRecordType.GetProperty(var Dest: TVarData; const V: TVarData; const Name: string): Boolean;
var
  fld: TField;
begin
  fld := TVarDataRecordData(V).DataSet.FindField(Name);
  result := (fld <> nil);
  if result then
    Variant(dest) := fld.Value;
end;

function TVarDataRecordType.SetProperty(const V: TVarData; const Name: string; const Value: TVarData): Boolean;
var
  fld: TField;
begin
  fld := TVarDataRecordData(V).DataSet.FindField(Name);
  result := (fld <> nil);
  if result then begin
    TVarDataRecordData(V).DataSet.Edit;
    fld.Value := Variant(Value);
  end;
end;
Como já havia citado, agora mudamos na nossa class helper para que o getCurrentRec retorne uma variant

function TDataSetHelper.GetCurrentRec: Variant; begin Result := VarDataRecordCreate(Self); end; É isso, agora podemos escrever o nosso código da seguinte maneira:


for Employee in QuEmployee do begin
  S := Trim(Format('%s %s', [Employee.First_Name, Employee.Last_Name]));
  if Employee.Hire_Date < EncodeDate(1991, 1, 1) then
    S := '*' + S;
   MemOutput.Lines.Add(S);
end;
ou


for Employee in QuEmployee do begin
  s := Employee.First_Name;
  Employee.First_Name := Employee.Last_Name;
  Employee.Last_Name := s;
end;
Com um pouco de imaginação e criatividade podemos melhorar muito o nosso trabalho no dia a dia.