演習 - GitHub Copilot ツールを使用してコード セクションをリファクターして改善する
GitHub Copilot は、コードの品質、信頼性、パフォーマンス、セキュリティを向上する変更を提案して、コードの更新を支援します。
この演習では、GitHub Copilot を使用して、次のコード セクションをリファクターおよび改善します。
リフレクションではなくディクショナリを使用するように EnumHelper クラスをリファクターします。 ディクショナリを使用すると、リフレクションのオーバーヘッドが軽減され、パフォーマンスが向上します。 また、リフレクションを排除すると、コードの可読性、保守性、セキュリティも向上します。
foreach ループではなく LINQ (統合言語クエリ) を使用するようにデータ アクセス メソッドをリファクターします。 LINQ を使用すると、コレクション、データベース、XML ドキュメントのクエリを実行する、より簡潔で読みやすい方法が提供されます。 LINQ を使用すると、コードの可読性、保守性、パフォーマンスを向上させることができます。
GitHub Copilot を使用して EnumHelper クラスをリファクターする
リフレクションは、実行時にオブジェクトを検査および操作できる強力な機能です。 ただし、リフレクションには時間がかかる可能性があり、リフレクションに関連する潜在的なセキュリティ リスクを考慮する必要があります。
既存の EnumHelper クラスは、リフレクションを使用して列挙値の description 属性を取得します。 リフレクションではなくディクショナリを使用するように EnumHelper クラスをリファクターできます。 ディクショナリを使用すると、パフォーマンスが向上し、リフレクションの使用に関連するセキュリティ上の懸念が解消されます。
この演習では、GitHub Copilot を使用して、EnumHelper クラスのリファクターを支援します。
以下の手順に従って、演習のこのセクションを完了します。
ソリューション エクスプローラー ビューを使用して、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(); } } }
チャット ビューを開き、ファイル
EnumHelper.cs
、LoanExtensionStatus.cs
、LoanReturnStatus.cs
、MembershipRenewalStatus.cs
をチャット コンテキストに追加します。次のプロンプトを入力します。
@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.
このプロンプトは、GitHub Copilot に対し、リフレクションではなくディクショナリを使用するように EnumHelper クラスを更新する方法の説明を求めます。 また、列挙値ごとにディクショナリを使用するように更新されたコードも要求します。
少し時間をとって、GitHub Copilot から提供された説明を確認します。
説明は次のようなものになります。
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.
注
GitHub Copilot がディクショナリに正しい説明を事前設定しない場合は、GitHub Copilot 拡張機能が再起動を要求していないことを確認します。 している場合は、拡張機能を再起動し、プロンプトをもう一度試してください。
GitHub Copilot がお勧めする
EnumHelper
クラスを使用して、EnumHelper.cs ファイルを更新します。更新された
EnumHelper
クラスで、LoanExtensionStatus.cs
、LoanReturnStatus.cs
、MembershipRenewalStatus.cs
ファイルの列挙値が使用されていることを確認します。各列挙ファイルを開き、ディクショナリ内の列挙値が正しいことを確認します。 不整合がある場合は、GitHub Copilot で各列挙型のディクショナリを個別に更新します。 たとえば、
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.
必要に応じて、
LoanReturnStatus
およびMembershipRenewalStatus
列挙型に対して同じアプローチを使用します。少し時間をとって、
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() }; }
このコードは、パターン マッチングを使用して列挙型の型を判断し、適切なディクショナリから説明を取得します。
switch
ステートメントは列挙型value
の型を確認し、対応する説明をディクショナリから返します。 列挙値がディクショナリ内に見つからない場合、このメソッドは列挙値を文字列として返します。GitHub Copilot にこのコードをリファクターしてラムダ式を削除するように依頼すると、読みやすくなります。
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(); } }
ソリューションを構築してエラーがないことを確認します。
警告が表示されます。 今のところは無視しても構いません。
LINQ を使用するようにデータ アクセス メソッドを更新する
LINQ (言語統合クエリ) は、コレクション、データベース、XML ドキュメントに対し統一した方法でクエリを実行できるようにする C# の強力な機能です。 LINQ は、従来の foreach ループと比較して、データのクエリを実行するためのより簡潔で読みやすい方法を提供します。
演習のこのセクションには次のタスクが含まれています。
- LINQ を使用するように JsonData.cs のメソッドをリファクターします。
- LINQ を使用するように JsonLoanRepository.cs のメソッドをリファクターします。
- LINQ を使用するように JsonPatronRepository.cs のメソッドをリファクターします。
LINQ を使用するように JsonData.cs のメソッドをリファクターする
JsonData クラスには、次のデータ アクセス メソッドが含まれています。GetPopulatedPatron、GetPopulatedLoan、GetPopulatedBookItem、GetPopulatedBook。 これらのメソッドは、foreach ループを使用してコレクションを反復処理し、オブジェクトを設定します。 これらのメソッドをリファクターして LINQ を使用すると、コードの可読性と保守性が向上します。
以下の手順に従って、演習のこのセクションを完了します。
JsonData.cs ファイルを開きます。
GetPopulatedPatron
メソッドを選択します。GetPopulatedPatron
メソッドは、完全に事前設定されたPatron
オブジェクトを作成するように設計されています。 これは、Patron
の基本プロパティをコピーし、そのLoans
コレクションに詳細なLoan
オブジェクトを追加します。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; }
インライン チャットを開き、LINQ を使用してメソッドをリファクターするプロンプトを入力します。
#selection refactor selection to `return new Patron` using LINQ
少し時間を取って、おすすめの更新を確認します。
おすすめの更新は、次のコードのようになります。
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() }; }
まず、LINQ クエリを使用して
foreach (Loan loan in Loans!)
ループを置き換えます。 LINQ コードを配置すると、オブジェクト初期化子を使用して、オブジェクト プロパティを新しいPatron
オブジェクトに割り当てることができます。 これにより、populated
オブジェクトの個別のPatron
インスタンスの必要性が軽減されます。 全体的に、更新されたコードは短くなり、読みやすくなっています。このコードは、入力のパトロン
p
を使用して、いくつかの基本プロパティを新しいPatron
オブジェクトに割り当てます。 次に、入力のパトロンに関連付けられたローンをLoans
コレクションに設定し、GetPopulatedLoan
メソッドを使用して各ローンを変換します。Loans
コレクションに値を設定する LINQ コード行は次のように分解できます。-
Loans!
:Loans!
式は、Loans
コレクションにアクセスします。!
演算子は null 免除演算子であり、開発者はLoans
が null ではないと確信していることを示します。Loans
メソッドを呼び出す前に、GetPopulatedPatron
が適切に初期化されていることを確認する必要があります。 -
.Where(loan => loan.PatronId == p.Id)
:このコードは、入力のパトロンp
に属するもののみを含むように、ローンをフィルター処理します。 -
.Select(GetPopulatedLoan)
:このコードは、GetPopulatedLoan
メソッドを使用して、フィルター処理された各ローンを変換します。 -
.ToList()
:結果をList<Loan>
に変換します。
-
推奨される更新プログラムを受け入れるには、[ 同意する] を選択します。
GetPopulatedPatron
メソッドをリファクターする方法を見てきたので、LINQ を使用するようにGetPopulatedLoan
、GetPopulatedBookItem
、GetPopulatedBook
メソッドをリファクターすることもできます。同じアプローチを使用して、
GetPopulatedLoan
、GetPopulatedBookItem
、GetPopulatedBook
メソッドをリファクターします。たとえば、次のプロンプトを使用して 3 つのメソッドをリファクターします。
GetPopulatedLoan
メソッドの場合:#selection refactor selection to `return new Loan` using LINQ. Use `GetPopulatedBookItem` for the `BookItem` property. Use `Single` for BookItem and Patron properties.
GetPopulatedBookItem
メソッドの場合:#selection refactor selection to `return new BookItem` using LINQ. Use `GetPopulatedBook` and `Single` for the `BookItem` property.
GetPopulatedBook
メソッドの場合:#selection refactor selection to `return new Book` using LINQ. Use `Where` and `Select` for `Author` property. Use `First` author.
おすすめの更新を受け入れたら、少し時間を取って、コードの変更を確認します。
更新されたコードは、次のコードのようになります。
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() }; }
EXPLAIN スマート アクションを使用して、LINQ クエリの説明を確認します。
Explain スマート アクションは、コードで使用される LINQ クエリの詳細な説明を提供します。
たとえば、 メソッドで
GetPopulatedBook
スマート アクションを使用すると、Author
オブジェクトのBook
プロパティを設定するために使用される LINQ クエリの説明を表示できます。Author = Authors!.Where(a => a.Id == b.AuthorId).Select(a => new Author { Id = a.Id, Name = a.Name }).First()
Explain スマート アクションでは、
Book
オブジェクトのAuthor
プロパティを設定するために使用される LINQ クエリの詳細な説明が提供されます。たとえば、説明は次のようになります。
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.
ソリューションを構築してエラーがないことを確認します。
警告が表示されます。 今のところは無視しても構いません。
LINQ を使用するように JsonLoanRepository.cs のメソッドをリファクターする
JsonLoanRepository クラスには、GetLoan
および UpdateLoan
データ アクセス メソッドが含まれています。 これら 2 つのメソッドをリファクターし、foreach ループを LINQ に置き換えて、コードの可読性と保守性を向上させます。
以下の手順に従って、演習のこのセクションを完了します。
JsonLoanRepository.cs
ファイルを開きます。GetLoan
メソッドを選択します。GetLoan
メソッドは、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; }
インライン チャットを開き、LINQ を使用してメソッドをリファクターするプロンプトを入力します。
たとえば、次のプロンプトを入力します。
#selection refactor selection using LINQ with `_jsonData.Loans!. Use `Where`, `Select` and `GetPopulatedLoan` to return `FirstOrDefault`.
少し時間を取って、おすすめの更新を確認します。
おすすめの更新は、次のコードのようになります。
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; }
更新されたコードでは、LINQ を使用してローンのコレクションをフィルター処理し、指定された ID を持つローンのみを含めます。
loan
は Null 許容 (Loan? loan
) として宣言する必要があることに注意してください。 次に、GetPopulatedLoan
メソッドを使用してローンを変換し、最初の結果を返します。 一致するローンが見つからない場合、FirstOrDefault
はnull
を返します。 このメソッドは、指定されたid
を持つローンが存在しない場合は null 値となる可能性がある、このローン オブジェクトを返します。 このアプローチにより、返されたローンには必要なすべての関連データが完全に設定され、ローンのレコードの包括的なビューが提供されます。このコードはさらに簡略化できます。
public async Task<Loan?> GetLoan(int id) { await _jsonData.EnsureDataLoaded(); return _jsonData.Loans! .Where(l => l.Id == id) .Select(l => _jsonData.GetPopulatedLoan(l)) .FirstOrDefault(); }
更新された GetLoan メソッドを受け入れるには、[承諾] を選択 します。
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(); } }
インライン チャットを開き、LINQ を使用してメソッドをリファクターするプロンプトを入力します。
たとえば、次のプロンプトを入力します。
#selection refactor selection using LINQ find an existing loan `_jsonData.Loans!. Replace existing loan.
少し時間を取って、おすすめの更新を確認します。
おすすめの更新は、次のコードのようになります。
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(); } }
更新されたコードでは、LINQ を使用してローンのコレクション内の既存のローンを検索します。 次に、既存のローンを新しいローン データで更新します。 次に、このメソッドは更新されたローンのコレクションを保存し、データを再読み込みします。 このアプローチにより、ローン データが正しく更新され、変更がデータ ストアに保持されることが保証されます。
メソッドが実行される前にデータが確実に読み込まれるようにするコードを追加することもできます。
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(); } }
更新された UpdateLoan メソッドを受け入れるには、[承諾] を選択 します。
ソリューションを構築してエラーがないことを確認します。
警告が表示されます。 今のところは無視しても構いません。
LINQ を使用するように JsonPatronRepository のメソッドをリファクターする
JsonPatronRepository
クラスには、SearchPatrons
、GetPatron
、UpdatePatron
メソッドが含まれており、最適化の候補として有力です。 これらのメソッドをリファクターし、foreach ループを LINQ に置き換えて、コードの可読性と保守性を向上させます。
以下の手順に従って、演習のこのセクションを完了します。
JsonPatronRepository.cs
ファイルを開きます。SearchPatrons
メソッドを選択します。SearchPatrons
メソッドは、パトロンを名前で検索するように設計されています。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; }
インライン チャットを開き、LINQ を使用してメソッドをリファクターするプロンプトを入力します。
たとえば、次のプロンプトを入力します。
#selection refactor selection using LINQ with `_jsonData.Patrons!. Replace the loop with `Where`, `OrderBy`, and `GetPopulatedPatrons`.
少し時間を取って、おすすめの更新を確認します。
おすすめの更新は、次のコードのようになります。
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; }
更新された SearchPatrons メソッドを受け入れる場合は、Accept を選択してください。
GetPatron
メソッドを選択します。GetPatron
メソッドは、指定したid
に一致するパトロンを返すように設計されています。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; }
インライン チャットを開き、LINQ を使用してメソッドをリファクターするプロンプトを入力します。
たとえば、次のプロンプトを入力します。
#selection refactor selection using LINQ with `_jsonData.Patrons!. Use `Where`, `Select` and `GetPopulatedPatron` to return `FirstOrDefault`
少し時間を取って、おすすめの更新を確認します。
おすすめの更新は、次のコードのようになります。
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; }
このコードはさらに簡略化できます。
public async Task<Patron?> GetPatron(int id) { await _jsonData.EnsureDataLoaded(); return _jsonData.Patrons! .Where(p => p.Id == id) .Select(p => _jsonData.GetPopulatedPatron(p)) .FirstOrDefault(); }
更新された GetPatron メソッドを受け入れるには、[ 同意する] を選択します。
UpdatePatron
メソッドを選択します。UpdatePatron
メソッドは、指定されたid
でパトロンを更新するように設計されています。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(); } }
インライン チャットを開き、LINQ を使用してメソッドをリファクターするプロンプトを入力します。
たとえば、次のプロンプトを入力します。
#selection refactor selection using LINQ to find `patron` in `_jsonData.Patrons!. Replace existing patron with `patron`.
少し時間を取って、おすすめの更新を確認します。
おすすめの更新は、次のコードのようになります。
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(); } }
更新された UpdatePatron メソッドを受け入れるには、[ 同意する] を選択します。
作業を確認
作業内容を確認するには、以下の手順を実行します。
ソリューションをクリーンアップするには、
AccelerateAppDevGitHubCopilot
を右クリックし、[ クリーン] を選択します。このアクションにより、以前のビルドからビルド成果物が削除されます。 ソリューションをクリーンすると、JSON データ ファイルが (出力ディレクトリ内で) 元の値に効率的にリセットされます。
アプリケーションをビルドして、エラーがないことを確認します。
アプリケーションを実行します。
ソリューション エクスプローラー ビューからアプリケーションを実行するには、
Library.Console
プロジェクトを右クリックし、[ デバッグ] を選択し、[ 新しいインスタンスの開始] を選択します。パトロン名の入力を求められたら、「 One」 と入力し、Enter キーを押します。
「マッチング・パトロン」プロンプトで「 2 」と入力し、Enter キーを押します。
[貸し出しの予約] プロンプトで、「 1 」と入力し、Enter キーを押します。
[入力オプション] プロンプトで、「 r 」と入力し、Enter キーを押します。
"Book was successfully returned." というメッセージが表示されていることを確認します。
新しい検索を開始するには、「 s 」と入力し、Enter キーを押します。
パトロン名の入力を求められたら、「 One」 と入力し、Enter キーを押します。
「マッチング・パトロン」プロンプトで「 2 」と入力し、Enter キーを押します。
最初の書籍ローンが
Returned: True
とマークされていることを確認します。[入力オプション] プロンプトで、「 q 」と入力し、Enter キーを押します。
アプリケーションを停止します。