Digamos que precisamos passar as informações de uma nota fiscal, teríamos essa definição:
- Data de expedição – 10 caracteres;
- Nome do Cliente – 15 caracteres;
- Número da nota – 5 dígitos;
- Valor – 5 dígitos.
- Data: 01/01/2010;
- Nome: ALGUM NOME;
- Número: 123;
- Valor: 15.
A SOLUÇÃO ANTIGA
A solução que existia para facilitar isso era gerar uma classe de acordo com a definição dos campos, que retorna a string formatada. A classe gerada ficaria assim:class NotaFiscal { private string dataExpedicao; private string nomeCliente; private string numero; private string valor; public string DataExpedicao { get{return dataExpedicao;} set{dataExpedicao = Utils.FormataCaracteres(value, 10);} } public string NomeCliente { get{return nomeCliente;} set{nomeCliente = Utils.FormataCaracteres(value, 15);} } public string Numero { get{return numero;} set{numero = Utils.FormataDigitos(value, 5);} } public string Valor { get{return valor;} set{valor = Utils.FormataDigitos(value, 5);} } public string ObtemString() { return dataExpedicao + nomeCliente + numero + valor; } }
- todos os dados são strings, não é usada a tipagem da linguagem (int, string, DateTime);
- a definição de tipo e tamanho dos campos fica espalhada pelo código;
- a ordem dos campos precisa ser verificada dentro da função ObtemString;
- caso alguma modificação seja feita nos campos, fica ruim de dar manutenção nesse código.
A Nova solução
A solução que procurei desenvolver tinha alguns pré-requisitos, entre eles:- a classe não deveria ter informações relacionadas aos campos que seriam montados na string (definição de tipo, tamanho, etc);
- poder utilizar os tipos da linguagem (int, DateTime, Enum);
- a definição de mapeamento da classe para a string a ser gerada deveria ser clara e facilmente editável;
Com isso temos uma classe de modelo, contendo os dados devidamente tipados e um mapeamento que define quais campos serão transportados para a string, o formato e a posição. Todas essas informações conseguimos obter usando reflection e o mapeamento definido.
class NotaFiscal { public DateTime DataExpedicao { get; set; } public string NomeCliente { get; set; } public int Numero { get; set; } public int Valor { get; set; } }
<mapping class=”NotaFiscal”> <field name=”DataExpedicao” Length=”10” /> <field name=”NomeCliente” Length=”15” /> <field name=”Numero” Length=”5” /> <field name=”Valor” Length=”5” /> </mapping>
Como você pode ver, não é necessário definir o tipo do campo pois ele é inferido à partir do tipo utilizado no modelo. Ou seja, sabemos que um DateTime deverá ser convertido para o formato yyyy-MM-dd, um inteiro deve ser preenchidos com zeros a esquerda e uma string com espaços a direita.
Para obter a string à partir de um modelo, o que precisa ser feito é chamar um método assim:
conversor.GetString(meuModelo);
Implementando a solução
A implementação não tem muito segredo é apenas uma questão de obter cada valor do nosso modelo seguindo a definição do XML.O ponto mais importante é a conversão do valor tipado para a string. Como cada tipo tem um formato específico, criei um conversor para cada um. Por exemplo:
class IntConverter : ITypeConverter { public string GetString(Field field, object value) { int valorInteiro = Convert.ToInt32(value); return valorInteiro.ToString().PadLeft(‘0’, field.Length); } }