quarta-feira, 5 de dezembro de 2012

Convertendo Enumeradores em sua Entidade e Retornando uma descrição amigável de forma Simples.

Nesse artigo iremos fazer uma conversao de dados em nossa entidade, em nosso exemplo possuimos uma entidade Usuario que possui uma propriedade chamada Status que guarda um Int que relaciona com o status do usuario. Esses status estao representados no enum StatusEnum, conforme abaixo:
    public enum StatusEnum
    {
        [Description("Usuário em Analise")]
        EmAnalise = 1,
        [Description("Usuário Autorizado")]
        Autorizado = 2,
        [Description("Usuário Banido")]
        Banido = 3,
    }
 
Interessante é criar uma Classe Estática Util com um metodo para capturar o Description e apresentar em nossa camada de Apresentação.
 
        public static class Util
 {
        public static string ObterDescricaoStatusEnum(StatusSolicitacaoEnum valor) {
            FieldInfo fieldInfo = valor.GetType().GetField(valor.ToString());

            DescriptionAttribute[] atributos = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

            return atributos.Length > 0 ? atributos[0].Description ?? "Nulo" : valor.ToString();
        } 
 }
 
Agora vamos dar uma olhada em nossa Entidade Usuario.

Poderiamos fazer as alterações direto no código da entidade, mas caso estejamos usando um ORM como EF ou Linq to Sql teriamos um problema a cada atualização do banco de dados pois qualquer código que colocassemos seria sobrescrito. Para resolver esse problema o ideal é criamos uma classe separada para cada entidade, mas utilizando o PARTIAL e inserindo nossas regras, conforme exemplo abaixo:
 public partial class Usuario
    {
        string _StatusString;
        public string StatusString
        {
            get
            {
                switch (this.Status)
                {
                    case 1:
                        _StatusString = Util.ObterDescricaoStatusEnum(StatusSolicitacaoEnum.EmAnalise);
                        break;
                    case 2:
                        _StatusString = Util.ObterDescricaoStatusEnum(StatusSolicitacaoEnum.Autorizado);
                        break;
                    case 3:
                        _StatusString = Util.ObterDescricaoStatusEnum(StatusSolicitacaoEnumBanido);
                        break;
                }
                return _StatusString;
            }
        }
 }
 
Agora possuimo uma nova propriedade que podemos acessar via entidade, segue exemplo:
 Usuario usuario = new Usuario();
 string Status = usuario.StatusString;
 

Adendo

Nos comentarios, um desenvolvedor, sugeriu algumas melhorias, que apliquei após corrigir um equivoco cometido pelo nosso colega, esse equivoco nos levava a possuir duplicação de código, mas ao ajustar a idéia do companheiro o resultado ficou muito elegante segue o codigo:
        public static string ObterDescricao(this Enum valor)
        {
            FieldInfo fieldInfo = valor.GetType().GetField(valor.ToString());

            DescriptionAttribute[] atributos = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

            return atributos.Length > 0 ? atributos[0].Description ?? "Nulo" : valor.ToString();
        }
Para Obtermos a descrição o código ficaria assim:
public partial class Usuario
   {
       string _StatusString;
       public string StatusString
       {
           get
           {
               switch (this.Status)
               {
                   case 1:
                       _StatusString = StatusSolicitacaoEnum.EmAnalise.ObterDescricao();
                       break;
                   case 2:
                       _StatusString = StatusSolicitacaoEnum.Autorizado.ObterDescricao();
                       break;
                   case 3:
                       _StatusString = StatusSolicitacaoEnum.Banido.ObterDescricao();
                       break;
               }
               return _StatusString;
           }
       }
}
Espero que o artigo tenha ajudado a todos. Por favor curtam nossa Page no facebook assim poderemos criar mais artigos e lancar mais videos. https://www.facebook.com/arquiteturadotnet

2 comentários:

  1. A dica é interessante, mas pode ser melhorada em dois aspectos:

    1) Utilizar um método de extensão ao invés de uma classe de Utilitario

    public static string ObterDescricao(this StatusSolicitacaoEnum valor)

    Deste modo o método pode ser invocado assim:

    this.Status.ObterDescricao()

    O que em minha humilde opnião melhora um pouco a legibilidade do código.

    2) Caso este enum seja extensivamente utilizado(Uma chamada a este método obter descrição para cada usuário da base por exemplo),seria legal incluir algum tipo de política de cache(como por exemplo um dicionário enum/descricao), uma vez que operações que fazem uso de reflection podem/são custosas.

    ResponderExcluir
  2. Sua observacao é interessante mas como construiu esta contra os principios SOLID de OO, pois vc teria que implementar essa extensao para cada enum pois especificou um enum "(this StatusSolicitacaoEnum valor)"
    E a forma de invocar esta errada
    this.Status.ENUMERADOR.ObterDescricao()

    A forma correta para implementar o que disse sendo aplicado a qualquer enummerador seria

    public static string ObterDescricao(this Enum valor)

    mas foi boa a observação feito os ajustes ficou perfeito

    ResponderExcluir