Esercizio: eseguire il refactoring e migliorare le sezioni di codice usando gli strumenti di GitHub Copilot

Completato

GitHub Copilot consente di aggiornare il codice suggerendo modifiche che migliorano la qualità, l'affidabilità, le prestazioni e la sicurezza del codice.

In questo esercizio si usa GitHub Copilot per effettuare il refactoring e migliorare le sezioni di codice seguenti:

  • Viene eseguito il refactoring della classe EnumHelper per usare dizionari anziché reflection. L'uso dei dizionari migliora le prestazioni riducendo il sovraccarico della reflection. L'eliminazione della reflection migliora anche la leggibilità, la gestibilità e la sicurezza del codice.

  • Viene eseguito il refactoring dei metodi di accesso ai dati per usare LINQ (Language Integrated Query) anziché cicli foreach. L'uso di LINQ offre un modo più conciso e leggibile per eseguire query su raccolte, database e documenti XML. L'uso di LINQ può migliorare la leggibilità, la gestibilità e le prestazioni del codice.

Usare GitHub Copilot per effettuare il refactoring della classe EnumHelper

La reflection è una funzionalità potente che consente di ispezionare e manipolare oggetti nel runtime. Tuttavia, la reflection può essere lenta e alla reflection sono associati potenziali rischi per la sicurezza che devono essere presi in considerazione.

La classe EnumHelper esistente usa la reflection per recuperare l'attributo descrizione di un valore di enumerazione. È possibile eseguire il refactoring della classe EnumHelper per usare dizionari anziché reflection. L'uso di dizionari può migliorare le prestazioni ed eliminare eventuali problemi di sicurezza associati all'uso della reflection.

In questo esercizio si usa GitHub Copilot per effettuare il refactoring della classe EnumHelper.

Per completare questa sezione dell'esercizio, seguire questa procedura:

  1. Usare la vista Esplora soluzioni per aprire il file EnumHelper.cs.

    using System.ComponentModel;
    using System.Reflection;
    
    namespace Library.ApplicationCore.Enums;
    
    public static class EnumHelper
    {
        public static string GetDescription(Enum value)
        {
            if (value == null)
                return string.Empty;
    
            FieldInfo fieldInfo = value.GetType().GetField(value.ToString())!;
    
            DescriptionAttribute[] attributes =
                (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
    
            if (attributes != null && attributes.Length > 0)
            {
                return attributes[0].Description;
            }
            else
            {
                return value.ToString();
            }
        }
    }
    
  2. Aprire la visualizzazione Chat e quindi aggiungere i file seguenti al contesto chat: EnumHelper.cs, LoanExtensionStatus.cs, LoanReturnStatus.cs, MembershipRenewalStatus.cs.

  3. Immettere la richiesta seguente:

    @workspace I want to refactor the `EnumHelper` class using dictionaries rather than reflection to get enum description attributes. I want a separate dictionary for each enum. The enum values are in the `LoanExtensionStatus.cs`, `LoanReturnStatus.cs`, and `MembershipRenewalStatus.cs` files. Explain how to update the EnumHelper class to use dictionaries and provide the updated code.
    

    Questo prompt chiede a GitHub Copilot di fornire una spiegazione di come aggiornare la classe EnumHelper per usare dizionari anziché reflection. Chiede inoltre il codice aggiornato che usa dizionari per ogni valore di enumerazione.

  4. Esaminare la spiegazione fornita da GitHub Copilot.

    La spiegazione dovrebbe essere simile alla descrizione seguente:

    To refactor the `EnumHelper` class to use dictionaries for each enum, you need to create a dictionary for each enum type that maps the enum values to their descriptions. This will eliminate the need for reflection at runtime.
    
    Here's how you can update the `EnumHelper` class:
    
    1. Create dictionaries for each enum type.
    2. Populate these dictionaries with the enum values and their corresponding descriptions.
    3. Update the `GetDescription` method to use these dictionaries.
    
    Below is the updated code for the EnumHelper class:
    
    
    using System.ComponentModel;
    using System.Collections.Generic;
    
    namespace Library.ApplicationCore.Enums
    {
        public static class EnumHelper
        {
            private static readonly Dictionary<MembershipRenewalStatus, string> MembershipRenewalStatusDescriptions = new()
            {
                { MembershipRenewalStatus.Success, "Membership renewal was successful." },
                { MembershipRenewalStatus.PatronNotFound, "Patron not found." },
                { MembershipRenewalStatus.TooEarlyToRenew, "It is too early to renew the membership." },
                { MembershipRenewalStatus.LoanNotReturned, "Cannot renew membership due to an outstanding loan." },
                { MembershipRenewalStatus.Error, "Cannot renew membership due to an error." }
            };
    
            private static readonly Dictionary<LoanReturnStatus, string> LoanReturnStatusDescriptions = new()
            {
                { LoanReturnStatus.Success, "Book was successfully returned." },
                { LoanReturnStatus.LoanNotFound, "Loan not found." },
                { LoanReturnStatus.AlreadyReturned, "Cannot return book as the book is already returned." },
                { LoanReturnStatus.Error, "Cannot return book due to an error." }
            };
    
            private static readonly Dictionary<LoanExtensionStatus, string> LoanExtensionStatusDescriptions = new()
            {
                { LoanExtensionStatus.Success, "Book loan extension was successful." },
                { LoanExtensionStatus.LoanNotFound, "Loan not found." },
                { LoanExtensionStatus.LoanExpired, "Cannot extend book loan as it already has expired. Return the book instead." },
                { LoanExtensionStatus.MembershipExpired, "Cannot extend book loan due to expired patron's membership." },
                { LoanExtensionStatus.LoanReturned, "Cannot extend book loan as the book is already returned." },
                { LoanExtensionStatus.Error, "Cannot extend book loan due to an error." }
            };
    
            public static string GetDescription(Enum value)
            {
                if (value == null)
                    return string.Empty;
    
                return value switch
                {
                    MembershipRenewalStatus status => MembershipRenewalStatusDescriptions[status],
                    LoanReturnStatus status => LoanReturnStatusDescriptions[status],
                    LoanExtensionStatus status => LoanExtensionStatusDescriptions[status],
                    _ => value.ToString()
                };
            }
        }
    }
    
    
    This refactored EnumHelper class uses dictionaries to store the descriptions for each enum type. The GetDescription method now uses pattern matching to determine the type of the enum and retrieves the description from the appropriate dictionary. This approach avoids the use of reflection and improves performance.
    
    

    Nota

    Se GitHub Copilot non popola i dizionari con le descrizioni corrette, assicurarsi che l'estensione GitHub Copilot non richieda un riavvio. In tal caso, riavviare l'estensione e ritentare il prompt.

  5. Usare la classe EnumHelper suggerita di GitHub Copilot per aggiornare il file EnumHelper.cs.

  6. Assicurarsi che la classe EnumHelper aggiornata usi i valori di enumerazione dei file LoanExtensionStatus.cs, LoanReturnStatus.cse MembershipRenewalStatus.cs.

    Aprire ognuno dei file di enumerazione e verificare che i valori di enumerazione nei dizionari siano corretti. In caso di discrepanze, è necessario che GitHub Copilot aggiorni i dizionari per ogni enumerazione singolarmente. Ad esempio, è possibile usare il prompt seguente per l'enumerazione LoanExtensionStatus:

    @workspace Use the description values in LoanExtensionStatus.cs to update the LoanExtensionStatus dictionary in the EnumHelper class. Provide the updated code for the LoanExtensionStatus dictionary in the EnumHelper class.
    

    Se necessario, usare lo stesso approccio per le enumerazioni LoanReturnStatus e MembershipRenewalStatus.

  7. Rivedere il metodo GetDescription.

    public static string GetDescription(Enum value)
    {
        if (value == null)
            return string.Empty;
    
        return value switch
        {
            MembershipRenewalStatus status => MembershipRenewalStatusDescriptions[status],
            LoanReturnStatus status => LoanReturnStatusDescriptions[status],
            LoanExtensionStatus status => LoanExtensionStatusDescriptions[status],
            _ => value.ToString()
        };
    }
    

    Questo codice usa criteri di ricerca per determinare il tipo di enumerazione e recuperare la descrizione dal dizionario appropriato. L'istruzione switch controlla il tipo di enumerazione value e restituisce la descrizione corrispondente dal dizionario. Se il valore di enumerazione non viene trovato nel dizionario, il metodo restituisce il valore di enumerazione come stringa.

    Se si chiede a GitHub Copilot di effettuare il refactoring di questo codice ed eliminare le espressioni lambda, diventa più semplice da leggere:

    public static string GetDescription(Enum value)
    {
        if (value == null)
            return string.Empty;
    
        switch (value)
        {
            case MembershipRenewalStatus status:
                return MembershipRenewalStatusDescriptions[status];
            case LoanReturnStatus status:
                return LoanReturnStatusDescriptions[status];
            case LoanExtensionStatus status:
                return LoanExtensionStatusDescriptions[status];
            default:
                return value.ToString();
        }
    }
    
  8. Compilare la soluzione per assicurarsi che non siano presenti errori.

    Verranno visualizzati avvisi. Puoi ignorarli per il momento.

Aggiornare i metodi di accesso ai dati per usare LINQ

LINQ (Language Integrated Query) è una potente funzionalità di C# che consente di eseguire query su raccolte, database e documenti XML in modo uniforme. LINQ offre un modo più conciso e leggibile per eseguire query sui dati rispetto ai cicli foreach tradizionali.

Questa sezione dell'esercizio include le attività seguenti:

  • Eseguire il refactoring dei metodi in JsonData.cs per usare LINQ.
  • Eseguire il refactoring dei metodi in JsonLoanRepository.cs per usare LINQ.
  • Eseguire il refactoring dei metodi in JsonPatronRepository.cs per usare LINQ.

Eseguire il refactoring dei metodi in JsonData.cs per usare LINQ

La classe JsonData include i metodi di accesso ai dati seguenti: GetPopulatedPatron, GetPopulatedLoan, GetPopulatedBookItem, GetPopulatedBook. Questi metodi usano cicli foreach per iterare raccolte e popolare oggetti. È possibile eseguire il refactoring di questi metodi per usare LINQ per migliorare la leggibilità e la gestibilità del codice.

Per completare questa sezione dell'esercizio, seguire questa procedura:

  1. Aprire il file JsonData.cs.

  2. Seleziona il metodo GetPopulatedPatron.

    Il metodo GetPopulatedPatron è progettato per creare un oggetto Patron completamente popolato. Copia le proprietà di base di Patron e popola la relativa raccolta Loans con oggetti Loan dettagliati.

    public Patron GetPopulatedPatron(Patron p)
    {
        Patron populated = new Patron
        {
            Id = p.Id,
            Name = p.Name,
            ImageName = p.ImageName,
            MembershipStart = p.MembershipStart,
            MembershipEnd = p.MembershipEnd,
            Loans = new List<Loan>()
        };
    
        foreach (Loan loan in Loans!)
        {
            if (loan.PatronId == p.Id)
            {
                populated.Loans.Add(GetPopulatedLoan(loan));
            }
        }
    
        return populated;
    }
    
  3. Aprire una chat inline e quindi immettere un prompt che esegue il refactoring del metodo usando LINQ.

    #selection refactor selection to `return new Patron` using LINQ
    
  4. Rivedere l'aggiornamento suggerito.

    L'aggiornamento suggerito dovrebbe essere simile al codice seguente:

    public Patron GetPopulatedPatron(Patron p)
    {
        return new Patron
        {
            Id = p.Id,
            Name = p.Name,
            ImageName = p.ImageName,
            MembershipStart = p.MembershipStart,
            MembershipEnd = p.MembershipEnd,
            Loans = Loans!
                .Where(loan => loan.PatronId == p.Id)
                .Select(GetPopulatedLoan)
                .ToList()
        };
    }
    

    Innanzitutto, viene usata una query LINQ per sostituire il ciclo foreach (Loan loan in Loans!). Con il codice LINQ, è possibile usare un inizializzatore di oggetto per assegnare proprietà dell'oggetto al nuovo oggetto Patron. In questo modo si riduce la necessità di un'istanza populated separata dell'oggetto Patron. Nel complesso, il codice aggiornato è più breve e più leggibile.

    Il codice usa il cliente di input p per assegnare alcune proprietà di base al nuovo oggetto Patron. Quindi popola la raccolta Loans con prestiti associati al cliente di input, trasformando ogni prestito tramite il metodo GetPopulatedLoan.

    È possibile suddividere la riga di codice LINQ che popola la raccolta Loans:

    • Loans!: L'espressione Loans! accede alla raccolta Loans. L'operatore ! è un operatore null-forgiving, indicante che lo sviluppatore è sicuro che Loans non sia null. È necessario assicurarsi che Loans sia inizializzato correttamente prima di chiamare il metodo GetPopulatedPatron.
    • .Where(loan => loan.PatronId == p.Id): Questo codice filtra i prestiti in modo da includere solo quelli che appartengono al cliente di input p.
    • .Select(GetPopulatedLoan): Questo codice trasforma ogni prestito filtrato usando il metodo GetPopulatedLoan.
    • .ToList(): Converte il risultato in List<Loan>.
  5. Per accettare l'aggiornamento suggerito, selezionare Accetta.

    Ora che è stato illustrato come eseguire il refactoring del metodo GetPopulatedPatron, è possibile effettuare il refactoring dei metodi GetPopulatedLoan, GetPopulatedBookIteme GetPopulatedBook per usare anche LINQ.

  6. Eseguire il refactoring dei metodi GetPopulatedLoan, GetPopulatedBookItem e GetPopulatedBook usando lo stesso approccio.

    Ad esempio, usare i prompt seguenti per effettuare il refactoring dei tre metodi:

    Per il metodo GetPopulatedLoan:

    #selection refactor selection to `return new Loan` using LINQ. Use `GetPopulatedBookItem` for the `BookItem` property. Use `Single` for BookItem and Patron properties.
    

    Per il metodo GetPopulatedBookItem:

    #selection refactor selection to `return new BookItem` using LINQ. Use `GetPopulatedBook` and `Single` for the `BookItem` property.
    

    Per il metodo GetPopulatedBook:

    #selection refactor selection to `return new Book` using LINQ. Use `Where` and `Select` for `Author` property. Use `First` author.
    
  7. Dopo aver accettato gli aggiornamenti suggeriti, rivedere le modifiche apportate al codice.

    Il codice completato dovrebbe risultare simile al codice seguente:

    public Loan GetPopulatedLoan(Loan l)
    {
        return new Loan
        {
            Id = l.Id,
            BookItemId = l.BookItemId,
            PatronId = l.PatronId,
            LoanDate = l.LoanDate,
            DueDate = l.DueDate,
            ReturnDate = l.ReturnDate,
            BookItem = GetPopulatedBookItem(BookItems!.Single(bi => bi.Id == l.BookItemId)),
            Patron = Patrons!.Single(p => p.Id == l.PatronId)
        };
    }
    
    public BookItem GetPopulatedBookItem(BookItem bi)
    {
        return new BookItem
        {
            Id = bi.Id,
            BookId = bi.BookId,
            AcquisitionDate = bi.AcquisitionDate,
            Condition = bi.Condition,
            Book = GetPopulatedBook(Books!.Single(b => b.Id == bi.BookId))
        };
    }
    
    public Book GetPopulatedBook(Book b)
    {
        return new Book
        {
            Id = b.Id,
            Title = b.Title,
            AuthorId = b.AuthorId,
            Genre = b.Genre,
            ISBN = b.ISBN,
            ImageName = b.ImageName,
            Author = Authors!.Where(a => a.Id == b.AuthorId).Select(a => new Author {
                Id = a.Id,
                Name = a.Name
            }).First()
        };
    }
    
  8. Usare la smart action Spiegalo per visualizzare una spiegazione delle query LINQ.

    La smart action Spiegalo fornisce una spiegazione dettagliata delle query LINQ usate nel codice.

    Ad esempio, è possibile usare la smart action Spiegalo sul metodo GetPopulatedBook per visualizzare una spiegazione della query LINQ usata per popolare la proprietà Author dell'oggetto Book.

    Author = Authors!.Where(a => a.Id == b.AuthorId).Select(a => new Author {
        Id = a.Id,
        Name = a.Name
    }).First()
    

    La smart action Spiegalo fornisce una spiegazione della query LINQ usata per popolare la proprietà Author dell'oggetto Book.

    Ad esempio, la spiegazione potrebbe essere simile alla seguente:

    The active selection is a C# code snippet that assigns a value to the Author property. This value is derived from a collection of Author objects named Authors. The code uses LINQ (Language Integrated Query) to filter and transform the data within this collection.
    
    First, the Authors! expression uses the null-forgiving operator (!) to indicate that Authors is not null, even if the compiler might think otherwise. This is a way to suppress nullable warnings. The Where method is then called on the Authors collection to filter the elements. The lambda expression a => a.Id == b.AuthorId is used to find all Author objects where the Id matches the AuthorId property of another object b.
    
    After filtering, the Select method is used to project each filtered Author object into a new Author object. This is done by creating a new instance of the Author class and copying the Id and Name properties from the original Author object.
    
    Finally, the First method is called to retrieve the first element from the resulting sequence. This means that the Author property will be assigned the first Author object that matches the filter criteria and has been projected into a new Author instance.
    
    This approach ensures that the Author property is set to a new Author object with the same Id and Name as the first matching Author in the Authors collection.
    
  9. Compilare la soluzione per assicurarsi che non siano presenti errori.

    Verranno visualizzati avvisi. Puoi ignorarli per il momento.

Eseguire il refactoring dei metodi in JsonLoanRepository.cs per usare LINQ

La classe JsonLoanRepository include i metodi di accesso ai dati GetLoan e UpdateLoan. Verrà eseguito il refactoring di questi due metodi, sostituendo i cicli foreach con LINQ per migliorare la leggibilità e la gestibilità del codice.

Per completare questa sezione dell'esercizio, seguire questa procedura:

  1. Apri il file JsonLoanRepository.cs.

  2. Seleziona il metodo GetLoan.

    Il metodo GetLoan è progettato per recuperare un prestito in base al relativo ID.

    public async Task<Loan?> GetLoan(int id)
    {
        await _jsonData.EnsureDataLoaded();
    
        foreach (Loan loan in _jsonData.Loans!)
        {
            if (loan.Id == id)
            {
                Loan populated = _jsonData.GetPopulatedLoan(loan);
                return populated;
            }
        }
    
        return null;
    }
    
  3. Aprire una chat inline e quindi immettere un prompt che esegue il refactoring del metodo usando LINQ.

    Ad esempio, immettere il prompt seguente:

    #selection refactor selection using LINQ with `_jsonData.Loans!. Use `Where`, `Select` and `GetPopulatedLoan` to return `FirstOrDefault`.
    
  4. Rivedere l'aggiornamento suggerito.

    L'aggiornamento suggerito dovrebbe essere simile al codice seguente:

    public async Task<Loan?> GetLoan(int id)
    {
        await _jsonData.EnsureDataLoaded();
    
        Loan? loan = _jsonData.Loans!
            .Where(l => l.Id == id)
            .Select(l => _jsonData.GetPopulatedLoan(l))
            .FirstOrDefault();
    
        return loan;
    }
    

    Il codice aggiornato usa LINQ per filtrare la raccolta di prestiti in modo da includere solo il prestito con l'ID specificato. Si noti che loan deve essere dichiarato come nullable (Loan? loan). Trasforma quindi il prestito usando il metodo GetPopulatedLoan e restituisce il primo risultato. Se non viene trovato alcun prestito corrispondente, FirstOrDefault restituisce null. Il metodo restituisce quindi questo oggetto prestito, che può essere null se non esiste alcun prestito con l'id specificato. Questo approccio garantisce che il prestito restituito sia completamente popolato con tutti i dati correlati necessari, fornendo una visione completa del record del prestito.

    Questo codice potrebbe essere ulteriormente semplificato:

    public async Task<Loan?> GetLoan(int id)
    {
        await _jsonData.EnsureDataLoaded();
    
        return _jsonData.Loans!
            .Where(l => l.Id == id)
            .Select(l => _jsonData.GetPopulatedLoan(l))
            .FirstOrDefault();
    
    }
    
  5. Per accettare il metodo GetLoan aggiornato, selezionare Accetta.

  6. Seleziona il metodo UpdateLoan.

    public async Task UpdateLoan(Loan loan)
    {
        Loan? existingLoan = null;
        foreach (Loan l in _jsonData.Loans!)
        {
            if (l.Id == loan.Id)
            {
                existingLoan = l;
                break;
            }
        }
    
        if (existingLoan != null)
        {
            existingLoan.BookItemId = loan.BookItemId;
            existingLoan.PatronId = loan.PatronId;
            existingLoan.LoanDate = loan.LoanDate;
            existingLoan.DueDate = loan.DueDate;
            existingLoan.ReturnDate = loan.ReturnDate;
    
            await _jsonData.SaveLoans(_jsonData.Loans!);
    
            await _jsonData.LoadData();
        }
    }
    
  7. Aprire una chat inline e quindi immettere un prompt che esegue il refactoring del metodo usando LINQ.

    Ad esempio, immettere il prompt seguente:

    #selection refactor selection using LINQ find an existing loan `_jsonData.Loans!. Replace existing loan.
    
  8. Rivedere l'aggiornamento suggerito.

    L'aggiornamento suggerito dovrebbe essere simile al codice seguente:

    public async Task UpdateLoan(Loan loan)
    {
        Loan? existingLoan = _jsonData.Loans!.FirstOrDefault(l => l.Id == loan.Id);
    
        if (existingLoan != null)
        {
            existingLoan.BookItemId = loan.BookItemId;
            existingLoan.PatronId = loan.PatronId;
            existingLoan.LoanDate = loan.LoanDate;
            existingLoan.DueDate = loan.DueDate;
            existingLoan.ReturnDate = loan.ReturnDate;
    
            await _jsonData.SaveLoans(_jsonData.Loans!);
    
            await _jsonData.LoadData();
        }
    }
    

    Il codice aggiornato usa LINQ per trovare il prestito esistente nella raccolta di prestiti. Aggiorna quindi il prestito esistente con i nuovi dati del prestito. Il metodo salva quindi la raccolta di prestiti aggiornata e ricarica i dati. Questo approccio garantisce che i dati del prestito vengano aggiornati correttamente e che le modifiche vengano mantenute nell'archivio dati.

    È anche possibile aggiungere il codice per assicurarsi che i dati vengano caricati prima dell'esecuzione del metodo:

    public async Task UpdateLoan(Loan loan)
    {
        await _jsonData.EnsureDataLoaded();
    
        Loan? existingLoan = _jsonData.Loans!.FirstOrDefault(l => l.Id == loan.Id);
    
        if (existingLoan != null)
        {
            existingLoan.BookItemId = loan.BookItemId;
            existingLoan.PatronId = loan.PatronId;
            existingLoan.LoanDate = loan.LoanDate;
            existingLoan.DueDate = loan.DueDate;
            existingLoan.ReturnDate = loan.ReturnDate;
    
            await _jsonData.SaveLoans(_jsonData.Loans!);
    
            await _jsonData.LoadData();
        }
    }
    
    
  9. Per accettare il metodo UpdateLoan aggiornato, selezionare Accetta.

  10. Compilare la soluzione per assicurarsi che non siano presenti errori.

    Verranno visualizzati avvisi. Puoi ignorarli per il momento.

Effettuare il refactoring dei metodi in JsonPatronRepository per usare LINQ

La classe JsonPatronRepository include i metodi SearchPatrons, GetPatron e UpdatePatron ed è un ottimo candidato per l'ottimizzazione. Verrà eseguito il refactoring di questi due metodi, sostituendo i cicli foreach con LINQ per migliorare la leggibilità e la gestibilità del codice.

Per completare questa sezione dell'esercizio, seguire questa procedura:

  1. Apri il file JsonPatronRepository.cs.

  2. Seleziona il metodo SearchPatrons.

    Il metodo SearchPatrons è progettato per cercare i clienti in base al nome.

    public async Task<List<Patron>> SearchPatrons(string searchInput)
    {
        await _jsonData.EnsureDataLoaded();
    
        List<Patron> searchResults = new List<Patron>();
        foreach (Patron patron in _jsonData.Patrons)
        {
            if (patron.Name.Contains(searchInput))
            {
                searchResults.Add(patron);
            }
        }
        searchResults.Sort((p1, p2) => String.Compare(p1.Name, p2.Name));
    
        searchResults = _jsonData.GetPopulatedPatrons(searchResults);
    
        return searchResults;
    }
    
  3. Aprire una chat inline e quindi immettere un prompt che esegue il refactoring del metodo usando LINQ.

    Ad esempio, immettere il prompt seguente:

    #selection refactor selection using LINQ with `_jsonData.Patrons!. Replace the loop with `Where`, `OrderBy`, and `GetPopulatedPatrons`.
    
  4. Rivedere l'aggiornamento suggerito.

    L'aggiornamento suggerito dovrebbe essere simile al codice seguente:

    public async Task<List<Patron>> SearchPatrons(string searchInput)
    {
        await _jsonData.EnsureDataLoaded();
    
        List<Patron> searchResults = _jsonData.Patrons!
            .Where(patron => patron.Name.Contains(searchInput))
            .OrderBy(patron => patron.Name)
            .ToList();
    
        searchResults = _jsonData.GetPopulatedPatrons(searchResults);
    
        return searchResults;
    }
    
  5. Per accettare il metodo SearchPatrons aggiornato, selezionare Accetta.

  6. Seleziona il metodo GetPatron.

    Il metodo GetPatron è progettato per restituire il cliente corrispondente al id specificato.

    public async Task<Patron?> GetPatron(int id)
    {
        await _jsonData.EnsureDataLoaded();
    
        foreach (Patron patron in _jsonData.Patrons!)
        {
            if (patron.Id == id)
            {
                Patron populated = _jsonData.GetPopulatedPatron(patron);
                return populated;
            }
        }
        return null;
    }
    
  7. Aprire una chat inline e quindi immettere un prompt che esegue il refactoring del metodo usando LINQ.

    Ad esempio, immettere il prompt seguente:

    #selection refactor selection using LINQ with `_jsonData.Patrons!. Use `Where`, `Select` and `GetPopulatedPatron` to return `FirstOrDefault`
    
  8. Rivedere l'aggiornamento suggerito.

    L'aggiornamento suggerito dovrebbe essere simile al codice seguente:

    public async Task<Patron?> GetPatron(int id)
    {
        await _jsonData.EnsureDataLoaded();
    
        var patron = _jsonData.Patrons!
            .Where(p => p.Id == id)
            .Select(p => _jsonData.GetPopulatedPatron(p))
            .FirstOrDefault();
    
        return patron;
    }
    

    Questo codice potrebbe essere ulteriormente semplificato:

    public async Task<Patron?> GetPatron(int id)
    {
        await _jsonData.EnsureDataLoaded();
    
        return _jsonData.Patrons!
            .Where(p => p.Id == id)
            .Select(p => _jsonData.GetPopulatedPatron(p))
            .FirstOrDefault();
    }
    
  9. Per accettare il metodo GetPatron aggiornato, selezionare Accetta.

  10. Seleziona il metodo UpdatePatron.

    Il metodo UpdatePatron è progettato per aggiornare il cliente con il id specificato.

    
    public async Task UpdatePatron(Patron patron)
    {
        await _jsonData.EnsureDataLoaded();
        var patrons = _jsonData.Patrons!;
        Patron existingPatron = null;
        foreach (var p in patrons)
        {
            if (p.Id == patron.Id)
            {
                existingPatron = p;
                break;
            }
        }
        if (existingPatron != null)
        {
            existingPatron.Name = patron.Name;
            existingPatron.ImageName = patron.ImageName;
            existingPatron.MembershipStart = patron.MembershipStart;
            existingPatron.MembershipEnd = patron.MembershipEnd;
            existingPatron.Loans = patron.Loans;
            await _jsonData.SavePatrons(patrons);
            await _jsonData.LoadData();
        }
    }
    
  11. Aprire una chat inline e quindi immettere un prompt che esegue il refactoring del metodo usando LINQ.

    Ad esempio, immettere il prompt seguente:

    #selection refactor selection using LINQ to find `patron` in `_jsonData.Patrons!. Replace existing patron with `patron`.
    
  12. Rivedere l'aggiornamento suggerito.

    L'aggiornamento suggerito dovrebbe essere simile al codice seguente:

    public async Task UpdatePatron(Patron patron)
    {
        await _jsonData.EnsureDataLoaded();
        var patrons = _jsonData.Patrons!;
        var existingPatron = patrons.FirstOrDefault(p => p.Id == patron.Id);
        if (existingPatron != null)
        {
            existingPatron.Name = patron.Name;
            existingPatron.ImageName = patron.ImageName;
            existingPatron.MembershipStart = patron.MembershipStart;
            existingPatron.MembershipEnd = patron.MembershipEnd;
            existingPatron.Loans = patron.Loans;
            await _jsonData.SavePatrons(patrons);
            await _jsonData.LoadData();
        }
    }
    
  13. Per accettare il metodo UpdatePatron aggiornato, selezionare Accetta.

Controlla il tuo lavoro

Per controllare il lavoro, usare i passaggi seguenti:

  1. Per pulire la soluzione, fare clic con il pulsante destro del mouse su AccelerateAppDevGitHubCopilot e quindi selezionare Pulisci.

    Questa azione rimuove tutti gli artefatti di compilazione dalla compilazione precedente. La pulizia della soluzione ripristinerà efficacemente i valori originari del file di dati JSON (nella directory di output).

  2. Compilare l'applicazione e assicurarsi che non siano presenti errori.

  3. Eseguire l'applicazione.

    È possibile eseguire l'applicazione dalla vista Esplora soluzioni facendo clic con il pulsante destro del mouse sul progetto Library.Console, selezionando Debug e quindi scegliendo Avvia nuova istanza.

  4. Quando viene chiesto il nome di un cliente, digitare Uno e quindi premere Invio.

  5. Al prompt "Clienti corrispondenti" digitare 2 e quindi premere Invio.

  6. Al prompt "Prestiti di libri" digitare 1 e quindi premere Invio.

  7. Al prompt "Opzioni di input", digitare r e quindi premere Invio.

  8. Assicurarsi che venga visualizzato il messaggio "Il libro è stato restituito correttamente".

  9. Per iniziare una nuova ricerca, digitare s e quindi premere Invio.

  10. Quando viene chiesto il nome di un cliente, digitare Uno e quindi premere Invio.

  11. Al prompt "Clienti corrispondenti" digitare 2 e quindi premere Invio.

  12. Assicurarsi che il primo prestito del libro sia contrassegnato Returned: True.

  13. Al prompt "Opzioni di input", digitare q e quindi premere Invio.

  14. Arrestare l'applicazione.