Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Solucionado (ver solução)

Não consigo obter em tempo de execução um tipo dinamicamente?

Após a aula me ocorreu de inverter um pouco a lógica pegando como base as propriedades e imprimindo elas na tela, pricipalmente pensando em 1 para N, como para exibir os detalhes de um cadastro, e usar de forma dinâmica para todas as classes que eu deseje. Então criei o código abaixo. Porém esbarrei na seguinte mensagem: "Os argumentos de tipo do método não podem ser inferidos com base no uso. Tente especificar explicitamente os argumentos de tipo".

Como faço para imprimir na tela dinamicamente todas as propriedades da classe, incluindo as listas como Telefones e Categorias?

Outra Pergunta: Tem uma forma mais elegante de identificar se a propriedade é uma classe, sem ser comparando com "System"?

Se tratado só a classe pessoa o resultado do Código é esse: TestReflection.Pessoa Nome: João da Silva Telefones: TestReflection.Telefones Categorias: TestReflection.Categorias

O Que eu desejo é: TestReflection.Pessoa Nome: João da Silva TestReflection.Telefones Tipo: 1 Numero: (11)9985-8554 Categorias: TestReflection.Categorias Tipo: 5 Descricao: Empresario

Veja o código:

    class Program
    {
        static void Main(string[] args)
        {
            List<Pessoa> listPeson = new List<Pessoa>();
            var person1 = new Pessoa();
            person1.Nome = "João da Silva";
            person1.Telefones = new Telefones { new Telefone { Tipo = 1, Numero = "(11)9985-8554" } };
            person1.Categorias = new Categorias { new Categoria { Tipo = 5, Descricao = "Empresario" } };
            listPeson.Add(person1);
            InformacaoDinamica(listPeson);
            Console.ReadLine();
        }

        public static void InformacaoDinamica<T>(List<T> listReg)
        {

            for (int i = 0; i < listReg.Count; i++)
            {
                Console.WriteLine(listReg[i].GetType());
                foreach (var propriedade in listReg[i].GetType().GetProperties())
                {
                    if (propriedade.PropertyType.FullName.StartsWith("System"))
                    {
                        Console.WriteLine($"{propriedade.Name}: {propriedade.GetValue(listReg[i], null)}");
                    }
                    else
                    {
                        InformacaoDinamica(propriedade.GetValue(listReg[i], null)); //Não Compila
                        //InformacaoDinamica((List<object>)propriedade.GetValue(listReg[i], null)); //Compila mas da mensagem que não pode converter lista generica em lista telefones
                    }
                }
            }
        }
    }


    class Pessoa
    {
        public string Nome { get; set; }
        public Telefones Telefones { get; set; }
        public Categorias Categorias { get; set; }
    }

    class Telefones : List<Telefone> { }
    class Telefone
    {
        public int Tipo { get; set; }
        public string Numero { get; set; }
    }

    class Categorias : List<Categoria> { }
    class Categoria

    {
        public int Tipo { get; set; }
        public string Descricao { get; set; }
    }

Desde já Obrigado

3 respostas
solução

Oi Matheus, tudo bem?

O código para varrer propriedades (inclusive coleções) de um objeto é meio trabalhoso de escrever, então me desculpe, estou usando um código feito por terceiros:

https://stackoverflow.com/a/20554262/1123307

public void PrintProperties(object obj, int indent)
{    
    if (obj == null) return;
    string indentString = new string(' ', indent);
    Type objType = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();
    foreach (PropertyInfo property in properties)
    {
        object propValue = property.GetValue(obj, null);
        var elems = propValue as IList;
        if (elems != null)
        {
            foreach (var item in elems)
            {
                PrintProperties(item, indent + 3);
            }
        }
        else
        {
            // This will not cut-off System.Collections because of the first check
            if (property.PropertyType.Assembly == objType.Assembly)
            {
                Console.WriteLine("{0}{1}:", indentString, property.Name);

                PrintProperties(propValue, indent + 2);
            }
            else
            {
                Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
            }
        }
    }
}

Sobre verificar se a propriedade é um primitivo ou não:

if (pi.GetType().IsPrimitive || pi.GetType() == typeof(string))

Onde: pi é o PropertyInfo, que estamos verificando se é um tipo primitivo (não-classe) ou uma string.

Obrigado pela resposta, Deu certo com o exemplo que você me passou, no caso só precisei verificar no início se trata-se de uma lista recebida, aí ficou como queria!

Obrigado

Excelente, Matheus! Sempre às ordens, e obrigado por participar do fórum!