0 C# - Construindo objetos de forma dinâmica
Neste artigo vou mostrar como podemos criar objetos dinâmicos usando a classe ExpandoObject na linguagem C#. |
A partir da versão 4.0 da linguagem C# foi introduzido o tipo dynamic.
O tipo dynamic é um tipo estático que é definido pela palavra reservada dynamic sendo que a princípio a variável desse tipo pode ser TUDO, e, em tempo de compilação o tipo dynamic assume qualquer operação.
Mesmo sendo um tipo estático a declaração dynamic faz com que o compilador não realize as validações estáticas sendo que as operações também somente serão avaliadas em tempo de execução.
Então vamos supor que eu precise criar e trabalhar com um objeto em tempo de execução. Como eu faria ?
Eu poderia usar um recurso que faz parte da dynamic language runtime (DLR) chamado ExpandoObject.
A classe ExpandoObject representa um objeto cujos membros podem ser adicionados e removidos no tempo de execução dinamicamente.
Vamos usar essa classe para criar um objeto onde podemos adicionar propriedades, métodos e eventos e ser capaz vincular o objeto com a interface do usuário.
Vamos usar a classe ExpandoObject para criar um objeto inicial que trata o nome e o pais de uma pessoa:
using System.Dynamic;
using static System.Console;
namespace CShp_Dynamic
{
class Program
{
static void Main(string[] args)
{
dynamic expando = new ExpandoObject();
expando.Nome = "Macoratti";
expando.Pais = "Brasil";
WriteLine($"{expando.Nome} reside no {expando.Pais}");
ReadLine();
}
}
}
|
No código acima adicionarmos propriedades diretamente mas podemos ir além, e adicionar propriedades de forma mais dinâmica ao nosso objeto.
Vamos então adicionar uma nova propriedade chamada Idioma usando o método AddProperty que criamos para esse propósito:
using System.Collections.Generic;
using System.Dynamic;
using static System.Console;
namespace CShp_Dynamic
{
class Program
{
static void Main(string[] args)
{
dynamic expando = new ExpandoObject();
expando.Nome = "Macoratti";
expando.Pais = "Brasil";
// Adicionando propriedades dinamicamente ao objeto expando
AddProperty(expando, "Idioma", "Português");
WriteLine($"{expando.Nome} reside no {expando.Pais} cujo idioma é o {expando.Idioma}");
ReadLine();
}
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
{
// ExpandoObject da suporte a IDictionary então podemos estendê-lo assim:
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
}
}
|
Para criar o objeto usamos a declaração dynamic expando = new ExpandoObject();
Note que eu não usei ExpandoObject() expando = new ExpandoObject(); a pois se fizesse isso o objeto expando seria um objeto tipado estaticamente do tipo ExpandoObject e neste caso eu não poderia adicionar membros em tempo de execução como fiz a seguir.
A vantagem em usar esse método que criamos é que usa o suporte que ExpandoObject possui a IDictionary<string,object> e permite incluir valores em tempo de execução.
Podemos continuar e agora adicionar métodos ao objeto do tipo ExpandoObject usando o tipo genérico Func<> o qual representa uma chamada de método.
Vamos definir um método chamado IsValid e usando o Func<> vamos incluir um método de validação para nosso objeto:
using System;
using System.Collections.Generic;
using System.Dynamic;
using static System.Console;
namespace CShp_Dynamic
{
class Program
{
static void Main(string[] args)
{
dynamic expando = new ExpandoObject();
expando.Nome = "";
expando.Pais = "Brasil";
// Adicionando propriedades dinamicamente ao objeto expando
AddProperty(expando, "Idioma", "Português");
// Adiciona um método a expando
expando.IsValid = (Func<bool>)(() =>
{
// verifica se foi fornecido um nome
if (string.IsNullOrWhiteSpace(expando.Nome))
return false;
return true;
});
if (!expando.IsValid())
{
WriteLine("O nome NÃO foi fornecido ao objeto expando.");
}
WriteLine($"{expando.Nome} reside no {expando.Pais} cujo idioma é o {expando.Idioma}");
ReadLine();
}
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)...
}
}
|
Agora vamos supor que eu queira criar uma lista de objetos contatos dinamicamente definindo as propriedades Nome, Telefone e Email.
Veja o código como fica:
dynamic contatos = new List<dynamic>();
contatos.Add(new ExpandoObject());
contatos[0].Nome = "Patricia Santos";
contatos[0].Telefone = "9206-55-44";
contatos[0].Email = "pati@homail.com";
contatos.Add(new ExpandoObject());
contatos[1].Nome = "Eliana Sanches";
contatos[1].Telefone = "9678-55-01";
contatos[1].Email = "eliana@uol.com.br";
foreach (var c in contatos)
WriteLine($"{ c.Nome} - {c.Telefone}");
ReadLine();
|
Eu
poderia definir a lista de contatos usando o seguinte código :
dynamic contatos
= new List<ExpandoObject>()
e o exemplo continuaria funcionando.
No entanto, existem algumas situações em que isso pode causar problemas, porque
o tipo real dos elementos da lista deve ser dynamic e não
ExpandoObject, e estes são dois tipos diferentes. Mais uma vez, as
referências aos objetos ExpandoObject seriam tipadas estaticamente e não
suportam operações dinâmicas.
E estamos conversados...
"Disse-lhe Jesus: Eu
sou o caminho, e a verdade e a vida; ninguém vem ao Pai, senão por mim"
João 14:6
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
LINQ - Consultas Dinâmicas usando LINQ Dynamic ... - Macoratti.net