quarta-feira, 8 de setembro de 2010

Dynamic CRUD no .NET 4.0

No último artigo fizemos um overview sobre programação dinâmica e as possibilidades que ela oferece, e terminamos, com uma idéia sobre um CRUD a partir do banco. Hoje veremos como isso poderia ser feito.

A idéia é usarmos o DLR (Dynamic Language Runtime) para que nosso código compilado ignore a estrutura estática dos tipos que podem ser detectados na compilação, ou seja, ter a verificação de tipos somente no momento da execução. Dessa forma, vamos até o momento de dados, obtemos o schema da tabela que desejamos e criamos a estrutura de um objeto correspondente a ela. Depois disso, montamos a rotina para inserção de registros na base (na tabela ao qual a entidade se refere) e criamos na entidade o método que executa esse rotina.

Para que tudo isso seja possível precisamos conhecer o intermediario de toda essa “mágica”, portanto, lhes apresento o “ExpandoObject”.

A classe ExpandoObject pertence ao namespace System.Dynamic e é definida no assembly System.Core e representa um objeto cujos membros podem ser dinamicamente adicionados e removidos em tempo de execução.

public sealed class ExpandoObject :
    IDynamicMetaObjectProvider,
    IDictionary<string, object>,
    ICollection<KeyValuePair<string, object>,
    IEnumerable<KeyValuePair<string, object>>,
    IEnumerable,
    INotifyPropertyChanged


Na verdade, é a interface “IDynamicMetaObjectProvider” quem permite que um objeto seja compartilhado no DLR (Dynamic Language Runtime) por programas escritos de acordo com o modelo de interoperabilidade DLR, ou seja, apenas os objetos que implementam essa interface podem ser compartilhados em linguagens dinâmicas do .NET.

Dynamic CRUD


A idéia aqui é criarmos um objeto contendo todas as propriedades da tabela e os métodos do CRUD (do Inglês Create, Read, Update e Delete), porém, por questões de simplicidade, nosso exemplo focará apenas na inserção de dados (Create).

A figura abaixo representa a estrutura que criaremos:



O grande astro dessa solução é classe “Entity”, que é a responsável por criar uma instância e adicionar as propriedades (de acordo com as colunas do banco) e o método de inclusão de dados.

O primeiro passo é criar uma instância de “ExpandoObject”, da mesma forma que qualquer outro objeto .NET, exceto pelo fato de que a variável para armazenar a instância é do tipo “dynamic”.

dynamic entity = new ExpandoObject();

Após buscarmos o schema da tabela na base de dados vamos adicionar as propriedades, e para isso, você apenas atribui a ela um novo valor, por exemplo:

entity.ExpandoEntityName = name;

Porém, não sabemos o nome das propriedades, afinal, os recuperamos a partir do schema da tabela, como fica?

Lembra que o “ExpandoObject” implementa a interface “IDictionary”? Então, é a parte “string” ou “key” é o nome da propriedade ou método, e a parte “object” ou “valor”, é valor da propriedade ou o delegate do método. Sendo assim, convertemos nosso “ExpandoObject” para “IDictionary” e através de um loop criamos todas as propriedades:

var e = (entity as IDictionary<string, object>);
foreach (var property in propertyList)
{
    e[property.Name] = "";
}


O mesmo serve para a criação do método de inserção:

entity.Insert = new Action(() => {
    SqlClientPlugin.Insert(tableName, entity, propertyList);
});

O uso dessa estrutura nos permitiria criar um código assim:

var company = Entity.NewEntity("Teste");

company.Name = "Apolineo Serviços de Informática Ltda.";
company.WebSite = "http://www.apolineo.com.br";

company.Insert();

Bom, isso é só uma possibilidade de uso de programação dinâmica e esperamos que sirva de estopim para outras grandes idéias de uso.

O código de exemplo pode ser obtido no link abaixo:
ExpandoObjetoTestSolution.rar

Até a próxima!