Exibir mensagem anterior :: Exibir próxima mensagem |
Autor |
Mensagem |
marcieldeg Colaborador
Registrado: Terça-Feira, 5 de Abril de 2011 Mensagens: 1054 Localização: Vitória - ES
|
Enviada: Seg Nov 06, 2017 9:42 am Assunto: Retornar o opção do enum a partir do nome do tipo e da opção |
|
|
Tenho o nome do tipo de um enum e a opção, todos em String. Como obter o tipo equivalente?
Exemplo:
Código: | type
TFruta = (tfAbacate, tfBanana, tfCaju);
var
Tipo, Valor: String;
Fruta: TFruta;
begin
Tipo := 'TFruta';
Valor := 'tfBanana';
Fruta := funcaoAqui(Tipo, Valor);
end; |
_________________ "Olha a interface da IDE! Será que ela é? Será que ela é? DELPHI!" |
|
Voltar ao Topo |
|
|
natanbh1 Colaborador
Registrado: Terça-Feira, 15 de Março de 2011 Mensagens: 3093 Localização: Belo Horizonte - MG
|
Enviada: Seg Nov 06, 2017 11:09 am Assunto: |
|
|
Não sei se vai ser o suficiente para te ajudar, mas criei uma função usando a unit TypInfo.
Pode ser melhorada, pois não consegui converter o parâmetro Tipo (string) para TFruta.
Função:
Código: | function getFruta(valor: string): TFruta;
begin
Result := TFruta(GetEnumValue(TypeInfo(TFruta), valor));
end; |
Exemplo de uso:
Código: | var
Fruta: TFruta;
begin
Fruta := getFruta('tfBanana');
end; |
Neste link tem outra maneira:
https://stackoverflow.com/questions/2472487/converting-an-string-to-a-enum-type-using-tvalue _________________ ''A persistência é o caminho para o êxito.''
Charlie Chaplin |
|
Voltar ao Topo |
|
|
strak2012 Colaborador
Registrado: Segunda-Feira, 13 de Janeiro de 2014 Mensagens: 1518 Localização: Maceió - AL
|
Enviada: Seg Nov 06, 2017 11:13 am Assunto: Re: Retornar o opção do enum a partir do nome do tipo e da opção |
|
|
marcieldeg escreveu: | Tenho o nome do tipo de um enum e a opção, todos em String. Como obter o tipo equivalente?
Exemplo:
Código: | type
TFruta = (tfAbacate, tfBanana, tfCaju);
var
Tipo, Valor: String;
Fruta: TFruta;
begin
Tipo := 'TFruta';
Valor := 'tfBanana';
Fruta := funcaoAqui(Tipo, Valor);
end; |
|
normalmente faço desta forma aqui:
Código: | type
TFruta = (tfAbacate, tfBanana, tfCaju);
function FrutaToString(value:TFruta):string; // retorna o nome do enumerador, acredito que com o uso da RTTI é possível buscar este valor
begin
result:='Desconhecido';
case value of
tfAbacate:result:='tfAbacate';
tfBanana:result:='tfBanana';
tfCaju:result:='tfCaju';
end;
end;
function StingToFruta(value:string):TFruta; // retorna o tipo do enumerador, aqui não há mesmo outra forma, nem mesmo com o RTTI, acredito eu, posso estar enganado
begin
if uppercase(value)=uppercase('tfAbacate') then result:=tfAbacate;
if uppercase(value)=uppercase('tfBanana') then result:=tfBanana;
if uppercase(value)=uppercase('tfCaju') then result:=tfCaju;
end;
var
Tipo, Valor: String;
Fruta: TFruta;
begin
Tipo := 'TFruta'; // Fruta ja seria um TFruta, logo bastaria de uma função que informasse apenas o nome do enumerador, a menos claro que estivesse a querer fazer typecast de outros types para Tfruta havendo claro uma equivalência, para isso ambos types deveria ser nomeados e enumerados.
Valor := 'tfBanana';
Fruta := StingToFruta(Valor);
end; |
a menos claro que estivesse a querer fazer typecast de outros types para Tfruta havendo claro uma equivalência, para isso ambos types deveria ser nomeados e enumerados.
Para caso de types diferente e com equivalências
Código: | type
TFruta = (tfAbacate=1, tfBanana=2, tfCaju=3);
TColorPen = (tfPreto=1, tfBranco=2, tfAzul=3); |
neste caso é possivel fazer typecas dos dois tipos
Código: | var
fruta1:TFruta;
pen1:TColorPen;
begin
pen1:=tfBranco;
fruta:=TFruta(integer(pen1));// cá é possível o type cast logo seria possivel criar uma função do tipo mencionada acima por vc funcaoAqui(Tipo, Valor);
end; |
não sei bem se ha a nescessidade de realizar um typecast para integer primeiro, sei que seria funcional desta forma, mais como ambos são enumerados é possivel que funcionasse apenas como TFruta(pen1); _________________ Tudo podemos quando tudo sabemos! |
|
Voltar ao Topo |
|
|
marcieldeg Colaborador
Registrado: Terça-Feira, 5 de Abril de 2011 Mensagens: 1054 Localização: Vitória - ES
|
Enviada: Seg Nov 06, 2017 12:01 pm Assunto: |
|
|
natanbh1 escreveu: | Não sei se vai ser o suficiente para te ajudar, mas criei uma função usando a unit TypInfo.
Pode ser melhorada, pois não consegui converter o parâmetro Tipo (string) para TFruta.
Função:
Código: | function getFruta(valor: string): TFruta;
begin
Result := TFruta(GetEnumValue(TypeInfo(TFruta), valor));
end; |
Exemplo de uso:
Código: | var
Fruta: TFruta;
begin
Fruta := getFruta('tfBanana');
end; |
Neste link tem outra maneira:
https://stackoverflow.com/questions/2472487/converting-an-string-to-a-enum-type-using-tvalue |
Preciso obter pelo nome do tipo do enum em String, pois é o retorno de um webservice.
Código: | <TFruta>tfBanana</TFruta> |
mas pode ser outro enum:
Código: | <TAnimal>tmAvestruz</TAnimal> |
ou "qualquer outra coisa".
Claro que não é "qualquer", os enums possívels estão em uma unit compartilhada pelos dois projetos (da aplicação cliente e do webservice). Mas há uma lista bem grande de enums. _________________ "Olha a interface da IDE! Será que ela é? Será que ela é? DELPHI!" |
|
Voltar ao Topo |
|
|
marcieldeg Colaborador
Registrado: Terça-Feira, 5 de Abril de 2011 Mensagens: 1054 Localização: Vitória - ES
|
Enviada: Seg Nov 06, 2017 12:07 pm Assunto: |
|
|
Cheguei a criar uma classe wrapper da TypInfo para retornar o enum pelo nome, mas com ela preciso do tipo do enum, ou seja, não me atende. Vou deixar a dica aqui caso alguém initeresse:
Código: |
type
TEnumUtils<T> = class
class function FromName(AName: String): T;
end;
class function TEnumUtils<T>.FromName(AName: String): T;
begin
PInteger(@Result)^ := GetEnumValue(TypeInfo(T), AName);
end; |
Uso:
Código: | fruta := TEnumUtils<TFruta>.FromName('tfBanana'); |
O objetivo é conseguir uma função tipo
Código: | function ValueFromEnumName(AEnumType, AEnumName: String): Integer; |
Que me retorna o valor ordinal de qualquer enum. _________________ "Olha a interface da IDE! Será que ela é? Será que ela é? DELPHI!" |
|
Voltar ao Topo |
|
|
strak2012 Colaborador
Registrado: Segunda-Feira, 13 de Janeiro de 2014 Mensagens: 1518 Localização: Maceió - AL
|
Enviada: Seg Nov 06, 2017 12:11 pm Assunto: |
|
|
Neste caso como se trata de uma retorno de webservice eu recomendaria o uso de uma extrutura record tipo
Código: | Type
Tretorno=record
Tipo:string; // poderá vim do webservice qualquer tipo
Valor:string; // poderá vim do webservice qualquer valor
end; |
O porque disso? Se eu tratar ele como um tipo enumerador eu estarei limitando minha aplicação a trabalhar apenas com os tipos previamente editado no código fonte de minha aplicação, e caso num futuro próximo este webservice introduza novos tipos e ou mude seus tipo minha aplicação toda vai apresentar erros não tratáveis, forçando-me a introduzir no codigo fonte os novos tipos ou as alteração e uma nova recompilação.
Sendo um record posso eu posso ir cadastrando os tipos e seus valores em uma tabela a medidas que os dados estão chegando sem qualquer problema futuros. _________________ Tudo podemos quando tudo sabemos! |
|
Voltar ao Topo |
|
|
marcieldeg Colaborador
Registrado: Terça-Feira, 5 de Abril de 2011 Mensagens: 1054 Localização: Vitória - ES
|
Enviada: Seg Nov 06, 2017 12:30 pm Assunto: |
|
|
strak2012 escreveu: | Neste caso como se trata de uma retorno de webservice eu recomendaria o uso de uma extrutura record tipo
Código: | Type
Tretorno=record
Tipo:string; // poderá vim do webservice qualquer tipo
Valor:string; // poderá vim do webservice qualquer valor
end; |
O porque disso? Se eu tratar ele como um tipo enumerador eu estarei limitando minha aplicação a trabalhar apenas com os tipos previamente editado no código fonte de minha aplicação, e caso num futuro próximo este webservice introduza novos tipos e ou mude seus tipo minha aplicação toda vai apresentar erros não tratáveis, forçando-me a introduzir no codigo fonte os novos tipos ou as alteração e uma nova recompilação.
Sendo um record posso eu posso ir cadastrando os tipos e seus valores em uma tabela a medidas que os dados estão chegando sem qualquer problema futuros. |
A sua sugestão não resolve o problema inicial, mas obrigado pela dica. _________________ "Olha a interface da IDE! Será que ela é? Será que ela é? DELPHI!" |
|
Voltar ao Topo |
|
|
johnny-walker Moderador
Registrado: Sábado, 4 de Outubro de 2003 Mensagens: 10653 Localização: Contagem/MG - BRAZIL
|
Enviada: Seg Nov 06, 2017 11:19 pm Assunto: |
|
|
Veja se desta forma te atende, se é que entendi o que você deseja:
Código: | type
TOrdem = (fPrimeiro, fSegundo, fTerceiro);
procedure TForm1.Button1Click(Sender: TObject);
var
I: Byte;
begin
ComboBox1.Items.Clear;
for I := Ord(Low(Ordem)) to Ord(High(Ordem)) do
ComboBox1.Items.Add(GetEnumName(TypeInfo(TOrdem), I));
end;
|
bye _________________ P.O.W.E.R B.Y D.E.L.P.H.I |
|
Voltar ao Topo |
|
|
marcieldeg Colaborador
Registrado: Terça-Feira, 5 de Abril de 2011 Mensagens: 1054 Localização: Vitória - ES
|
Enviada: Ter Nov 07, 2017 8:13 am Assunto: |
|
|
johnny-walker escreveu: | Veja se desta forma te atende, se é que entendi o que você deseja:
Código: | type
TOrdem = (fPrimeiro, fSegundo, fTerceiro);
procedure TForm1.Button1Click(Sender: TObject);
var
I: Byte;
begin
ComboBox1.Items.Clear;
for I := Ord(Low(Ordem)) to Ord(High(Ordem)) do
ComboBox1.Items.Add(GetEnumName(TypeInfo(TOrdem), I));
end;
|
bye |
Não é isso.
Usando seu exemplo
Código: | type
TOrdem = (fPrimeiro, fSegundo, fTerceiro); |
Preciso de uma função que receba os argumentos como string.
Código: | valor := funcao('TOrdem', 'fPrimeiro'); // valor deve receber 0 |
Os parâmetros obrigatoriamente são em String.
Talvez seja possível somente pelo nome do enum:
Código: | valor := funcao('fPrimeiro'); // valor deve receber 0 |
Já que no Delphi não posso ter 2 enumeradores com as mesmas opções. _________________ "Olha a interface da IDE! Será que ela é? Será que ela é? DELPHI!" |
|
Voltar ao Topo |
|
|
natanbh1 Colaborador
Registrado: Terça-Feira, 15 de Março de 2011 Mensagens: 3093 Localização: Belo Horizonte - MG
|
Enviada: Ter Nov 07, 2017 8:41 am Assunto: |
|
|
O 'X' da questão no seu caso é conseguir fazer este 'Cast' de String para o 'Nome' do tipo enumerado.
O conversão que vi foi do valor. Tanto de String para algum valor do tipo enumerado quanto vice-versa.
Nas pesquisas que fiz não vi nada neste sentido, não sei se é possível. _________________ ''A persistência é o caminho para o êxito.''
Charlie Chaplin |
|
Voltar ao Topo |
|
|
johnny-walker Moderador
Registrado: Sábado, 4 de Outubro de 2003 Mensagens: 10653 Localização: Contagem/MG - BRAZIL
|
Enviada: Ter Nov 07, 2017 12:45 pm Assunto: |
|
|
Eis aí, tente desta forma:
Código: | type
TEnumTest = (Primeriom, Segundo, Terceiro, Quarto, Quinto, Sexto, Setimo);
function StrToEnumTest(aStr:String):TEnumTest;
begin
result := TEnumTest(GetEnumValue(TypeInfo(TEnumTest) ,aStr));
end;
function EnumTestToStr(EnumTest: TEnumTest): string;
begin
Result := GetEnumName(TypeInfo(TEnumTest), Integer(EnumTest));
end;
procedure TForm1.Button1Click(Sender: TObject);
var
FSet: TEnumTest;
begin
FSet:= StrToEnumTest('Setimo');
ShowMessage(EnumTestToStr(FSet));
end;
|
Este utiliza generics:
https://stackoverflow.com/questions/2472487/converting-an-string-to-a-enum-type-using-tvalue
bye _________________ P.O.W.E.R B.Y D.E.L.P.H.I |
|
Voltar ao Topo |
|
|
marcieldeg Colaborador
Registrado: Terça-Feira, 5 de Abril de 2011 Mensagens: 1054 Localização: Vitória - ES
|
Enviada: Ter Nov 07, 2017 1:11 pm Assunto: |
|
|
marcieldeg escreveu: |
Preciso de uma função que receba os argumentos como string.
Código: | valor := funcao('TOrdem', 'fPrimeiro'); // valor deve receber 0 |
Os parâmetros obrigatoriamente são em String.
|
_________________ "Olha a interface da IDE! Será que ela é? Será que ela é? DELPHI!" |
|
Voltar ao Topo |
|
|
marcieldeg Colaborador
Registrado: Terça-Feira, 5 de Abril de 2011 Mensagens: 1054 Localização: Vitória - ES
|
Enviada: Ter Nov 07, 2017 1:15 pm Assunto: |
|
|
Estou tentando usar o método TRttiContext.FindType(), mas retorna null para enums.
Código: | function GetTypeInfoFromName(ATypeName: String): pTypeInfo;
var
C: TRttiContext;
T: TRttiType;
begin
T := TRttiContext.Create.FindType(ATypeName);
if not Assigned(T) then
raise Exception.CreateFmt('Type %s not found', [ATypeName]);
result := T.Handle;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
GetTypeInfoFromName('Unit1.TOrdem'); // retorna null
GetTypeInfoFromName('Unit1.TForm1'); // retorna certo
end; |
Se conseguir obter o TRttiType do enum, consigo recuperar os valores do enum. _________________ "Olha a interface da IDE! Será que ela é? Será que ela é? DELPHI!" |
|
Voltar ao Topo |
|
|
johnny-walker Moderador
Registrado: Sábado, 4 de Outubro de 2003 Mensagens: 10653 Localização: Contagem/MG - BRAZIL
|
|
Voltar ao Topo |
|
|
strak2012 Colaborador
Registrado: Segunda-Feira, 13 de Janeiro de 2014 Mensagens: 1518 Localização: Maceió - AL
|
Enviada: Ter Nov 07, 2017 1:45 pm Assunto: |
|
|
estive a olhar a extrutura do TypeInfo e até consegui pegar o nome do enumerador e seu valor
Código: | PTypeInfo(TypeInfo(TFruta)).Name // retorna o nome 'TFruta'
PTypeInfo(TypeInfo(TFruta)).TypeData.NameList // retorna o valor 'tfAbacate'
PTypeInfo(TypeInfo(TFruta)).Kind // reconhece que o type é um tkEnumeration |
Estou tentando usar estas informações em conjunto com o que foi postado pelo johnny-walker para ver se consigo confeccionar a função
Código: | function toType(tipo,valor:string) :pointer; |
O problema estar é pegar o type pelo nome para fazer um cast, e isso não me vem nada na cabeça a não ser arranjar uma forma de listar todos os types na aplicação para ir comparando com o argumento que foi inserido.
talvez mais alguém pode dá uma luz. _________________ Tudo podemos quando tudo sabemos! |
|
Voltar ao Topo |
|
|
|