Desenvolvimento - Delphi

Classe Genérica para Transformar Tipos ENUM Para TStrings em Delphi

Veja neste artigo como criar uma classe genérica que transforma tipos ENUM enumerados em TStrings usando o Delphi.

por Marco Antonio Salles



Quem é que nunca utilizou tipos enumerados para dar um suporte mais orientado à aplicação? Quem é que nunca precisou carregar um Tstrings com as opções do Tipo Enum? Quem é que nunca fez certas artimanhas para passar de String para ENUM e Vice-versa? Pois bem, o artigo de hoje não é somente mais uma das inúmeras opções que se encontram espalhadas na rede sobre o assunto, o propósito é criar um classe que seja desaclopada com um tipo Enum específico .

Com isto teremos mais flexibilidade e reaproveitamento do código em toda a VCL , onde tentamos andar sempre perto da POO , pois todo esforço a mais agora , será recompensado num futuro próximo .

Vamos ao código ???

Em uma Unit escreva a classe a seguir:

Listagem 1: Escrevendo Classes na Unit

unit uEnunConvertString;

interface
uses
   classes,Generics.Collections;

Type
  TGenerico = 0..255;

   TConvert<T:record> = class
     private
     public
       class procedure PopulateListEnum(AList: TStrings);
       class function StrConvertEnum(const AStr: string):T;
       class function EnumConvertStr(const eEnum:T):string;
     end;

implementation

uses
 Variants,SysUtils,TypInfo;

{ TConvert }

class procedure TConvert<T>.PopulateListEnum(AList: TStrings);
  var
   i:integer;
   StrTexto:String;
   Enum:Integer;
 begin
   i:=0;
   try
     repeat
       StrTexto:=trim(GetEnumName(TypeInfo(T), i));
       Enum:=GetEnumValue(TypeInfo(T),StrTexto);
       AList.Add(StrTexto);
       inc(i);
       until Enum < 0 ;
       AList.Delete(pred(AList.Count));
   except;
     raise EConvertError.Create(
                'O Parâmetro passado não corresponde a um Tipo ENUM');
   end;
 end;

{*******************************************************************************}

class function TConvert<T>.StrConvertEnum(const AStr: string):T;
 var
   P:^T;
   num:Integer;
 begin
   try
     num:=GetEnumValue(TypeInfo(T),Astr);
      if num = -1 then
        abort;
      P:=@num;
      result:=P^;
   except
     raise EConvertError.Create('
        O Parâmetro "'+Astr+'" passado não '+sLineBreak+
       ' corresponde a um Tipo Enumerado');
   end;
 end;

{******************************************************************************}

class function TConvert<T>.EnumConvertStr(const eEnum:T): String;
 var
   P:PInteger;
   Num:integer;
 begin
   try
     P:=@eEnum;
     Num:=integer(TGenerico((P^)));
     Result := GetEnumName(TypeInfo(T),Num);
   except
    raise EConvertError.Create(
             'O Parâmetro passado não corresponde a '+sLineBreak+
             'um inteiro Ou a um Tipo Enumerado');
   end;
 end;
end.

Algumas observações:

  • Esta unidade contém uma classe TConvert utilizando o conceito de Generics introduzido no Delphi2009.
  • Também aplicamos o conceito de Constraints utilizado neste caso para parametrizar o tipo genérico. Ao fizermos <T:record> definimos que o tipo real a ser utilizado deverá ser uma estrtutura de valor e não de referência, podendo ser um valor ordinário, ponto flutuante, ou um Record.
  • Limitamos com isto, que se use de forma errada a classe, restringindo mau uso e mau funcionamento da mesma. Por exemplo : TConvert.PopulateListEnum<TObject>() ; não chega nem a compilar.

Vamos agora fritar os bolinhos, afinal, uma classe deve fornecer os bolinhos para serem consumidos :

Em um formulário qualquer, vamos definir vários tipos a seguir enumerados:

  1. Type TAcao= (ftFirist, ftNext, ftPrior, FtLast, ftIgnore ) ;
  2. Type TRemuneracao = (ftHorario, ftDiario, FtSemanal , ftquinzenal , Ftmensal);
  3. Type TVencimentos = (ftMedia30, FtMedia45 , ftMedia60);
  4. Type TDinheiro = (ftReal , ftDollar , FtEuros, ftLibra , ftYen , ftPeso );
  5. Type TSorte = (ftPar , FtImpar);
  6. type TPort = (COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9);

Nosso primeiro objetivo é popular 6(seis) combobox respectivamente (cbAcao, cbRemuneracao, cbVencimentos, cbDinheiro, cbSorte, cbPort), utilizando a classe que se encontra na unidade UEnunConvertString. Para Isto De Uses a esta Unidade no Formulário que se encontra os 6(seis) Combobox e programe no evento onClick do Botão o seguinte Código:

Listagem 2: Programando evento onClick

procedure TForm1.btnPopularClick(Sender: TObject);
  begin
    TConvert<TAcao>.PopulateListEnum(CbAcao.Items);
    TConvert<TRemuneracao>.PopulateListEnum(cbRemuneracao.Items);
    TConvert<TVencimentos>.PopulateListEnum(cbVencimentos.Items);
    TConvert<TDinheiro>.PopulateListEnum(cbDinheiro.Items);
    TConvert<TSorte>.PopulateListEnum(cbSorte.Items);
    TConvert<TPort>.PopulateListEnum(cbPort.Items);
  end;

O Resultado são os 6(seis) Combobox “populados” sem alterarmos uma linha sequer do código. Esta Classe é expansível, flexível e suporta, a princípio, todos os tipos enumerados. Os outros métodos não vão ser detalhados, visto a sua simplicidade e alto didática. Se por ventura alguém tiver alguma dúvida na utilização desses métodos pode entrar em contado que será atendido.

Peço por último, por questões de gentileza e cordialidade, bem como respeito aos direitos autorais, que se alguém quiser acrescentar esta classe em algum veiculo de comunicação, que faça referência a fonte da informação original. No mais meu muito obrigado.

Blog do Autor: http://marcosalles.wordpress.com/

Marco Antonio Salles

Marco Antonio Salles - Um pouco de merchandising http://marcosalles.wordpress.com/ Se Deus não existe então Vale Tudo