1
resposta

[Bug] Erro ao criar dicionário da Documentação, como corrigir?

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Descrição: Erro CS1061 ‘IEnumerable’ não contém uma definição para "Instrucao" e não foi possível encontrar nenhum método de extensão "Instrucao" que aceite um primeiro argumento do tipo ‘IEnumerable’ (você está se esquecendo de usar uma diretiva ou uma referência de assembly?)

using System.Reflection;

namespace Alura.Adopet.Console
{
    [DocComando(instrucao: "help",
            documentacao: "comando que exibe informações de ajuda.")]
    internal class Help
    {
        private Dictionary<string, DocComando> docs;
        public Help()
        {
            docs = Assembly.GetExecutingAssembly().GetTypes()
                    .Where(t => t.GetCustomAttributes<DocComando>().Any())
                    .Select(t => (t.GetCustomAttributes<DocComando>()!))
                    .ToDictionary(d => d.Instrucao);
        }
        public void ExibeDocumentacao(string[] parametros)
        {
            // se não passou mais nenhum argumento mostra help de todos os comandos
            if (parametros.Length == 1)
            {
                System.Console.WriteLine($"Adopet (1.0) - Aplicativo de linha de comando (CLI).");
                System.Console.WriteLine($"Realiza a importação em lote de um arquivos de pets.");
                System.Console.WriteLine($"Comando possíveis: ");
                System.Console.WriteLine($" adopet help comando que exibe informações da ajuda.");
                System.Console.WriteLine($" adopet help <NOME_COMANDO> para acessar a ajuda de um comando específico.");
                System.Console.WriteLine($" adopet import <ARQUIVO> comando que realiza a importação do arquivo de pets.");
                System.Console.WriteLine($" adopet show <ARQUIVO> comando que exibe no terminal o conteúdo do arquivo importado.");
                System.Console.WriteLine($" adopet list comando que exibe no terminal o conteúdo cadastrado na base de dados da AdoPet." + "\n");
            }
            // exibe o help daquele comando específico
            else if (parametros.Length == 2)
            {
                string comandoASerExibido = parametros[1];
                if (comandoASerExibido.Equals("import"))
                {
                    System.Console.WriteLine($"adopet import <arquivo> " +
                        "comando que realiza a importação do arquivo de pets.");
                }
                if (comandoASerExibido.Equals("show"))
                {
                    System.Console.WriteLine($"adopet show <arquivo>  comando que " +
                        "exibe no terminal o conteúdo do arquivo importado.");
                }
                if (comandoASerExibido.Equals("list"))
                {
                    System.Console.WriteLine($"adopet list comando que exibe no terminal o conteúdo cadastrado na base de dados da AdoPet.");
                }
            }
        }
    }
}
1 resposta

Oii, Yuri, tudo bem?

O erro aconteceu porque você está tentando acessar uma propriedade Instrucao diretamente de uma coleção de atributos DocComando. O método GetCustomAttributes<DocComando>() retorna uma coleção de atributos, e não um único atributo.

Para corrigir esse problema, você precisa garantir que está acessando um único DocComando de cada tipo antes de tentar acessar a propriedade Instrucao. Isso pode ser feito modificando a parte do seu código que faz o .Select().

Aqui um exemplo de como você pode fazer isso:

using System.Reflection;

namespace Alura.Adopet.Console
{
    [DocComando(instrucao: "help",
            documentacao: "comando que exibe informações de ajuda.")]
    internal class Help
    {
        private Dictionary<string, DocComando> docs;
        public Help()
        {
            docs = Assembly.GetExecutingAssembly().GetTypes()
                    .Where(t => t.GetCustomAttributes<DocComando>().Any())
                    .Select(t => t.GetCustomAttributes<DocComando>().First()) // Alteração aqui
                    .ToDictionary(d => d.Instrucao);
        }
        // Restante do código...
    }
}

No código acima usei o método .First() para garantir que estamos pegando o primeiro atributo de cada tipo.

Se outra dúvida surgir, estamos aqui no fórum para te ajudar :)

Abraços e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.