Вот еще один подход, который заключается в создании класса, представляющего MenuItem
, который имеет описание и связанный метод, который следует вызывать, если выбран этот элемент.
private class MenuItem
{
public string Description { get; set; }
public Action Execute { get; set; }
}
Затем мы можем заполнить список этих предметов, которые будут показаны в MainMenu
// Our private list of menu items that will be displayed to the user
private static List<MenuItem> MenuItems;
// A helper method to populate our list.
// We can easily add or remove new items to the menu
// without having to worry about changing an
// enum or adding a command to a switch block
private static void PopulateMenuItems()
{
MenuItems = new List<MenuItem>
{
new MenuItem {Description = "View balance", Execute = ViewBalance},
new MenuItem {Description = "Deposit", Execute = Deposit},
new MenuItem {Description = "Withdraw", Execute = Withdraw},
};
}
Обратите внимание, что у каждого элемента есть свойство Execute
, которое имеет тип Action
, и им назначены значения выше. Эти значения на самом деле являются методами, которые могут быть определены в другом месте в проекте. Каждый метод в настоящее время является просто заглушкой, которая вызывает вспомогательный метод для отображения заголовка и другой вспомогательный метод, чтобы предложить пользователю вернуться в главное меню, но они могут содержать реальную функциональность:
private static void ViewBalance()
{
ClearAndShowHeading("Account Balance");
GoToMainMenu();
}
private static void Deposit()
{
ClearAndShowHeading("Account Deposit");
GoToMainMenu();
}
private static void Withdraw()
{
ClearAndShowHeading("Account Withdrawl");
GoToMainMenu();
}
private static void ClearAndShowHeading(string heading)
{
Console.Clear();
Console.WriteLine(heading);
Console.WriteLine(new string('-', heading?.Length ?? 0));
}
private static void GoToMainMenu()
{
Console.Write("\nPress any key to go to the main menu...");
Console.ReadKey();
MainMenu();
}
Итак, теперь у нас есть список пунктов меню, мы можем просто создать метод для их отображения, который также получит пользовательский ввод для выбранного элемента, а затем вызовет связанный метод (через свойство Execute
).
Обратите внимание, что здесь также выполняется некоторая проверка, чтобы гарантировать, что пользователь только выбирает действительный элемент. Мы показываем элементы на основе их индекса в списке (мы добавляем один к индексу, чтобы список не начинался с 0.
), а затем мы передаем пользовательский ввод методу int.TryParse
. Этот метод попытается проанализировать ввод пользователя в целое число. Если синтаксический анализ успешен, метод возвращает true
(и наш цикл завершается), а параметр out
будет содержать значение.
Это делается внутри цикла, поэтому, если пользователь вводит недопустимое число, то мы возвращаем курсор к началу строки, записываем пробел над ней, а затем снова устанавливаем курсор на начало, чтобы запросить их для ввода:
static void MainMenu()
{
ClearAndShowHeading("Main Menu");
// Write out the menu options
for (int i = 0; i < MenuItems.Count; i++)
{
Console.WriteLine($" {i + 1}. {MenuItems[i].Description}");
}
// Get the cursor position for later use
// (to clear the line if they enter invalid input)
int cursorTop = Console.CursorTop + 1;
int userInput;
// Get the user input
do
{
// These three lines clear the previous input so we can re-display the prompt
Console.SetCursorPosition(0, cursorTop);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, cursorTop);
Console.Write($"Enter a choice (1 - {MenuItems.Count}): ");
} while (!int.TryParse(Console.ReadLine(), out userInput) ||
userInput < 1 || userInput > MenuItems.Count);
// Execute the menu item function
MenuItems[userInput - 1].Execute();
}
Теперь, благодаря этому, очень легко настроить элементы меню, показать их пользователю и выполнить соответствующие методы соответствующим образом:
static void Main(string[] args)
{
PopulateMenuItems();
MainMenu();
Console.Write("\nDone! Press any key to exit...");
Console.ReadKey();
}
Попробуйте и посмотрите, что вы думаете. Меню будет выглядеть примерно так:
А что если мы хотим добавить новый пункт меню? Просто! Добавьте эту строку в блок кода, где мы присваиваем элементы MenuItems
внутри метода PopulateMenuItems
, и запустите ее снова:
new MenuItem {Description = "Exit", Execute = Application.Exit}
Теперь наше меню выглядит так: