Falta pouco!

0 dias

0 horas

0 min

0 seg

6
respostas

Não entendi de onde ele tira o args[1] no LeitorDeArquivo

Dá onde vem o args do program?

var leitorDeArquivos = new LeitorDeArquivo(caminhoDoArquivoASerLido: args[1]);

No meu está dando um erro que não era pra dar

private readonly LeitorDeArquivo _leitorDeArquivo = new LeitorDeArquivo("");

GitHub: https://github.com/IgorTudisco/Boas_Praticas-CSharp

6 respostas

Segue o meu teste:


using Alura.Adopet.Console.Comandos;
using Alura.Adopet.Console.Modelos;
using Alura.Adopet.Console.Servicos;
using Alura.Adopet.Console.Util;
using Moq;
using System.Threading.Tasks;

namespace Alura.Adopet.Testes;

public class ImportTeste
{
    [Fact]
    public async Task QuandoApiEstaNoArDeveRetornarListaDePet()
    {
        var leitorDeArquivo = new Mock<LeitorDeArquivo>(MockBehavior.Default, It.IsAny<string>());
        var listaDePets = new List<Pet>();
        var pet = new Pet(new Guid("456b24f4-19e2-4423-845d-4a80e8854a41"), "Lima", TipoPet.Cachorro);
        listaDePets.Add(pet);

        leitorDeArquivo.Setup(x => x.RealizaLeitura("")).Returns(listaDePets);

        var httpClientPet = new HttpClientPet(new AdopetAPIClientFactory().GetHttpClient());
        var import = new Import(httpClientPet, leitorDeArquivo.Object);
        string[] args = { "import", "lista.csv" };
        //Act
        await import.ExecutaAsync(args);
        //Assert 
        var listaPet = await httpClientPet.ListPetsAsync();
        Assert.NotNull(listaPet);

    }
}

Oi Igor! Como vai?

O args que você está vendo no código é um array de strings que contém os argumentos passados para o programa quando ele é executado. Quando você executa um programa C# a partir da linha de comando, você pode passar argumentos para ele, e esses argumentos são acessados dentro do programa através do array args.

Por exemplo, se você executar seu programa com o comando:

dotnet run import lista.csv

O array args conterá dois elementos:

  • args[0] será "import"
  • args[1] será "lista.csv"

No seu caso, o erro pode estar ocorrendo porque você não está passando argumentos suficientes ao executar o programa. Se você tentar acessar args[1] sem que ele tenha sido fornecido, o programa lançará uma exceção.

Para corrigir isso, certifique-se de que está passando os argumentos corretamente ao executar o programa. Se você está rodando o programa em um ambiente de desenvolvimento, como o Visual Studio, você pode configurar os argumentos de linha de comando nas propriedades do projeto.

Espero ter ajudado e bons estudos!

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

Não entendi muito bem como ele pega o args. Ele faz isso de forma automática ao passar o run?

dotnet run import lista.csv

Mas para ele pegar esse args ele tem que está declarado no Program.cs?

Montando ou não o meu leitor de arquivos (class LeitorDeArquivo) com o construtor, eu não consigo passar essa referência do args. Porque eu acho que o erro está dando porque eu não consigo capturar ele na minha classe ComandosDoSistema.

GitHub: https://github.com/IgorTudisco/Boas_Praticas-CSharp

Ainda assim, ele fica dando erro no args.

Segue a minha classe

using Alura.Adopet.Console.Servicos;
using Alura.Adopet.Console.Util;

namespace Alura.Adopet.Console.Comandos;

internal class ComandosDoSistema
{
    private readonly HttpClientPet _httpClientPet = new HttpClientPet(new AdopetAPIClientFactory().GetHttpClient());
    private readonly Dictionary<string, IComando> comandosDoSistema;
    // private readonly LeitorDeArquivo _leitorDeArquivo = new LeitorDeArquivo(caminhoDoArquivo: args[1]); // Erro, pois o args[1] não está disponível aqui
    private readonly LeitorDeArquivo _leitorDeArquivo = new LeitorDeArquivo();

    public ComandosDoSistema()
    {
        comandosDoSistema = new Dictionary<string, IComando>
        {
            {"help", new Help() },
            {"import", new Import(_httpClientPet, _leitorDeArquivo) },
            {"list", new List(_httpClientPet) },
            {"show",new Show(_leitorDeArquivo) },
        };
    }

    public IComando? this[string key] => comandosDoSistema.ContainsKey(key) ? comandosDoSistema[key] : null;
}

Segue também o meu leitor de arquivos:

using Alura.Adopet.Console.Modelos;

namespace Alura.Adopet.Console.Util;

public class LeitorDeArquivo
{
    private readonly string _caminhoDoArquivo;
    public LeitorDeArquivo(string? caminhoDoArquivo = "")
    {
        _caminhoDoArquivo = caminhoDoArquivo!;
    }

    public virtual List<Pet>? RealizaLeitura()
    {
        if (string.IsNullOrWhiteSpace(_caminhoDoArquivo))
        {
            return null;
        }

        List<Pet> listaDePets = new List<Pet>();
        using (StreamReader sr = new StreamReader(_caminhoDoArquivo))
        {
            System.Console.WriteLine("----- Serão importados os dados abaixo -----");
            while (!sr.EndOfStream)
            {
                var linha = sr.ReadLine()!;
                var pet = linha.ConverteDoTexto();
                listaDePets.Add(pet);
            }
        }

        return listaDePets;
    }
}

Oi, Igor! Perdão pela demora em responder!

O args só existe no método Main do Program.cs, porque ele é fornecido automaticamente pelo .NET quando você executa o programa com parâmetros na linha de comando (dotnet run import lista.csv). Por isso você não consegue usá-lo diretamente dentro da classe ComandosDoSistema.

Para resolver, você deve passar o argumento do args como parâmetro quando cria sua instância de ComandosDoSistema. Assim o args[1] chega até o LeitorDeArquivo. Veja como ajustar:


class Program
{
    static async Task Main(string[] args)
    {
        // aqui o args está disponível
        var comandos = new ComandosDoSistema(args);
        var comando = comandos[args[0]];
        if (comando != null)
        {
            await comando.ExecutaAsync(args);
        }
    }
}

Agora no seu ComandosDoSistema, adicione um construtor que receba os argumentos:


internal class ComandosDoSistema
{
    private readonly HttpClientPet _httpClientPet = new HttpClientPet(new AdopetAPIClientFactory().GetHttpClient());
    private readonly Dictionary<string, IComando> comandosDoSistema;
    private readonly LeitorDeArquivo _leitorDeArquivo;

    public ComandosDoSistema(string[] args)
    {
        // pega o args[1] aqui, onde o Program passou o valor
        _leitorDeArquivo = new LeitorDeArquivo(args.Length > 1 ? args[1] : "");

        comandosDoSistema = new Dictionary<string, IComando>
        {
            { "help", new Help() },
            { "import", new Import(_httpClientPet, _leitorDeArquivo) },
            { "list", new List(_httpClientPet) },
            { "show", new Show(_leitorDeArquivo) },
        };
    }

    public IComando? this[string key] => comandosDoSistema.ContainsKey(key) ? comandosDoSistema[key] : null;
}

Assim, o args[1] vem do Program.cs e é propagado corretamente para o LeitorDeArquivo, eliminando o erro que você comentou.

Fico à disposição.