C# - Converter List<T> para DataTable - I


Neste artigo veremos como converter uma lista genérica tipada para um DataTable na linguagem C#.

Trabalhar com coleções é algo que faz parte do dia a dia de um desenvolvedor em qualquer linguagem, e, a plataforma .NET oferece diversas classes que representam coleções, cada um com características próprias para facilitar a nossa vida.

A classe List(<T>) representa uma lista de objetos que podem ser acessados pelo índice e fornece métodos para pesquisar, ordenar e manipular listas. Ela é o equivalente genérico da classe ArrayList e implementa a interface genérica IList<(Of <(T>)>) usando uma matriz cujo tamanho é aumentado dinamicamente conforme necessário. O List(<T>) usa um comparador de igualdade e um comparador de classificação.

Um DataTable é como um container que podemos usar para armazenar informações de praticamente qualquer fonte de dados, sendo composto por uma coleção de linhas (rows) e colunas (columns)

 

Podemos criar um DataTable para armazenar dados em memória e realizar operações para incluir, alterar e excluir essas informações.

Neste artigo veremos como converter uma lista tipada de objetos List<T> em um DataTable.

recursos:

Criando o projeto Windows Forms no VS 2019 Community

Abra o VS 2019 Community e clique em Create a New Project. A seguir selecione:

Selecione o template:  Windows Forms App (.NET Framework) e clique em Next;

Informe o nome do projeto como : WF_Lista_DataTable e clique em Create.

No formulário Form1, inclua os controles:

Vamos criar uma classe Produto que será o tipo da nossa lista de objetos a converter:

public class Produto
{
        public int ProdutoId { get; set; }
        public string Nome { get; set; }
        public decimal Preco { get; set; }
}

Para gerar uma lista de objetos tipados do tipo produto vamos criar uma classe chamada DataService :

using System.Collections.Generic;
namespace WF_Lista_DataTable
{
    public class DataService
    {
        public static List<Produto> GetProdutos()
        {
            List<Produto> produtos = new List<Produto>();
            produtos.AddRange(new[]
            {
                   new Produto { ProdutoId=1, Nome="Caderno", Preco=6.00M },
                   new Produto { ProdutoId=2, Nome="Borracha", Preco=3.50M },
                   new Produto { ProdutoId=3, Nome="Lápis", Preco=2.99M },
                   new Produto { ProdutoId=4, Nome="Caneta", Preco=4.45M },
                   new Produto { ProdutoId=5, Nome="Régua", Preco=3.55M },
                   new Produto { ProdutoId=6, Nome="Estojo", Preco=6.60M },
              }
            );
            return produtos;
        }
        public static Produto GetProdutoCodigo(int id)
        {
            var produtos = getProdutos();
            return produtos[id];
        }
    }
}

Aqui , no método getProdutos() estamos gerando uma lista de objetos do tipo Produto. Aqui você pode obter a lista tipada de outras fontes.

O método getProdutoCodigo() recebe um inteiro e retorna um produto pelo seu código.

Agora desejamos converter esta lista para um DataTable para exibir no DataGridView do formulário Form1.

Para isso crie a classe CollectionHelper com o código abaixo:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Reflection;
namespace WF_Lista_DataTable
{
    public class CollectionHelper
    {
        private CollectionHelper()
        {}
        public static DataTable ConvertTo<T>(IList<T> list)
        {
            DataTable table = CreateTable<T>();
            Type entityType = typeof(T);
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType);
            foreach (T item in list)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                {
                    row[prop.Name] = prop.GetValue(item);
                }
                table.Rows.Add(row);
            }
            return table;
        }
        public static DataTable CreateTable<T>()
        {
            Type entityType = typeof(T);
            DataTable table = new DataTable(entityType.Name);
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType);
            foreach (PropertyDescriptor prop in properties)
            {
                table.Columns.Add(prop.Name, prop.PropertyType);
            }
            return table;
        }
    }
}

Nesta classe temos o método estático  ConvertTo<T>(IList<T> list) que recebe uma lista tipada e retornada um DataTable com ajuda do método CreateTable<T>.

Nota o código acima funciona para lista tipadas simples mas precisa de ajustes para cenários mais complexos.

Agora no formulário Form1, no evento Click do botão btnExibirDados inclua o código abaixo:

 private void BtnExibirDados_Click(object sender, EventArgs e)
 {
            DataTable tabela = CollectionHelper
                                     .ConvertTo<Produto>(DataService.getProdutos());
            dgvDados.DataSource = tabela;
}

Executando o projeto teremos o seguinte resultado:

Vemos assim a lista de objetos Produto sendo exibida no DataGridView após ser convertida para um DataTable.

Na segunda parte do artigo veremos como exibir os detalhes de um item da lista em outro formulário.

Referências:


José Carlos Macoratti