Sabemos que o XML é um formato largamente utilizado para representação, armazenamento e transferência de dados entre aplicações. Principalmente pela sua estrutura simples e pela sua “universalidade”, ou seja, é um formato reconhecido/suportado pela maioria das linguagens de programação que temos atualmente.

O .NET Framework, como não poderia deixar de ser, oferece grande suporte a essa linguagem de marcação, tornando fácil a criação e acesso a arquivos desse tipo.

Para exemplificar esta capacidade, vamos criar neste artigo uma pequena aplicação para armazenar itens em um arquivo XML, simulando um pequeno cadastro de clientes.

Então partiremos de uma aplicação Windows Forms já criada, dispensando a demonstração do processo de criação do projeto.

Desenvolveremos aqui uma estrutura baseada no padrão DAO, mas sem criar pastas ou nomenclaturas específicas, focando principalmente na funcionalidade do sistema.

A classe Cliente

A classe Cliente será a primeira adicionada ao nosso projeto e representará a camada BLL (Business Logic Layer). Essa classe terá apenas dois atributos: Nome e Email e seu código é apresentado na Listagem 1.

Listagem 1: Classe Cliente

public class Cliente
{
    #region Atributos
    private string _nome;
    private string _email;
    #endregion

    #region Propriedades
    public string Nome
    {
        get { return _nome; }
        set { _nome = value; }
    }

    public string Email
    {
        get { return _email; }
        set { _email = value; }
    }
    #endregion
}

Como esta classe faz parte da camada lógica, ela não fará acesso à base de dados, que nesse caso será o arquivo XML. Essa responsabilidade será dada a outra classe, que chamaremos de Clientes, no plural, indicando que ela representa uma coleção de objetos do tipo Cliente.

A classe Clientes fará parte do que seria a camada DAL (Data Access Layer), aquela que fica responsável por persistir os dados na base (arquivo XML).

Adicione então essa nova classe e utilize o código abaixo, que será melhor explicado mais adiante.

Listagem 2: Classe Clientes

public class Clientes
{
    private List<Cliente> _clientes;

    public Clientes()
    {
        this._clientes = new List<Cliente>();
    }

    public void Adicionar(Cliente cliente)
    {
        if (this._clientes.Count(c => c.Nome.Equals(cliente.Nome)) > 0)
        {
            throw new Exception("Já existe um cliente com este nome");
        }
        else
        {
            this._clientes.Add(cliente);
        }
    }

    public void Remover(Cliente cliente)
    {
        this._clientes.Remove(cliente);
    }

    public List<Cliente> ListarTodos()
    {
        return this._clientes;
    }

    public void Salvar()
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<Cliente>));
        FileStream fs = new FileStream("D://Clientes.xml", FileMode.OpenOrCreate);
        ser.Serialize(fs, this._clientes);
        fs.Close();
    }

    public void Carregar()
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<Cliente>));
        FileStream fs = new FileStream("D://Clientes.xml", FileMode.OpenOrCreate);
        try
        {            
            this._clientes = ser.Deserialize(fs) as List<Cliente>;
        }
        catch (InvalidOperationException ex)
        {
            ser.Serialize(fs, this._clientes);
        }
        finally
        {
            fs.Close();
        }
    }
}

Os métodos de adição, remoção e listagem são relativamente simples e até dispensam explicações. Voltemos nossa atenção para os métodos Salvar e Carregar. Nestes métodos utilizamos a classe XmlSerializer para salvar a lista de clientes em um arquivo e para carrega-la a partir dele. Ou seja, estaremos serializando e deserializando o objeto _clientes para um arquivo. No método Carregar, tratamos a exceção do tipo InvalidOperationException, que ocorre quando o arquivo XML não possuir conteúdo válido, o que é esperado no momento em que o arquivo for criado.

Se o arquivo XML não estiver no formato esperado, já serializamos a lista vazia para formatar o arquivo.

Para testar a estrutura de classes que criamos, podemos montar uma pequena interface no form principal da aplicação, apenas para invocar alguns dos métodos construídos.

A interface que utilizaremos neste artigo será bastante simples, conforma mostra a Figura 1.

Interface para teste das classes

Figura 1: Interface para teste das classes

O primeiro passo para testar nossas classes é declarar uma variável interna no form do tipo Clientes:

Listagem 3: Declarando uma instância da classe Clientes

private Clientes clientes;

Em seguida, no evento Load do form já podemos carregar nossa lista e exibir os dados no grid:

Listagem 4: Carregando a lista e exibindo no grid

private void Form1_Load(object sender, EventArgs e)
{
    clientes = new Clientes();
    clientes.Carregar();
    dataGridView1.DataSource = clientes.ListarTodos();
}

No primeiro momento, obviamente, essa lista estará vazia e o grid não listará nenhum item. Porém, ao codificarmos o evento Click do botão Cadastrar, poderemos informar o nome e o email de um cliente e adiciona-lo à lista.

Listagem 5: Cadastrando um cliente

private void btnCadastrar_Click(object sender, EventArgs e)
{
    Cliente cli = new Cliente()
    {
        Nome = txtNome.Text,
        Email = txtEmail.Text
    };

    clientes.Adicionar(cli);
    clientes.Salvar();
    dataGridView1.DataSource = null;
    dataGridView1.DataSource = clientes.ListarTodos();
}

Como vemos, as responsabilidades de cada classe estão bem definidas e estas oferecem uma interface simplificada para uso. Ou seja, só precisamos instanciar os objetos Cliente e adiciona-los à lista.

A classe Clientes ficará responsável por persistir os dados em um arquivo com extensão XML, que neste caso terá a seguinte estrutura:

Listagem 6: Arquivo XML com clientes gravados

<?xml version="1.0"?>
<ArrayOfCliente xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Cliente>
    <Nome>Joel</Nome>
    <Email>joelrlneto@gmail.com</Email>
  </Cliente>
  <Cliente>
    <Nome>maria</Nome>
    <Email>maria@email.com</Email>
  </Cliente>
  <Cliente>
    <Nome>Wesley</Nome>
    <Email>wesley123@email.com</Email>
  </Cliente>
</ArrayOfCliente>

Com o auxílio ainda da classe XmlSerializer, não precisamos nos preocupar com a forma como os dados serão armazenados, pois isso fica por conta da serialização XML.

A estrutura utilizada aqui é bastante simples, mas pode ser estendida para uma aplicação maior sem problemas, bastando manter a organização do código e divisão correta de funções.

Caso tenha alguma dúvida sobre o conteúdo abordado neste artigo, fique à vontade para usar a seção de comentários logo abaixo.