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:


José Carlos Macoratti