Формат имени меню изменения списка [C #] - PullRequest
0 голосов
/ 28 сентября 2018

У меня проблема с форматированием, как я хочу отображать элементы перечисления в окне консоли.

На данный момент метод Menu отображает элементы перечисления следующим образом:

[1] CreateCustomer
[2] CreateAccount
[3] SetAccountBalance
[4] DisplayAccount Balance
[5] Exit

Что я пытаюсь сделать, так это добавить соответствующие пробелы между каждым пунктом меню.Например, «CreateCustomer» для «Create Customer», «SetAccountBalance» для «Set Balance Account».

Перечисление выбора меню

enum MenuSelection
{
   CreateCustomer = 1,
   CreateAccount = 2,
   SetAccountBalance = 3,
   DisplayAccountBalance = 4,
   Exit = 5,
   MaxMenuSelection = 5,
}

Отображение метода меню

public static void Menu()
{
  for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
  {
     Console.WriteLine($"[{i}] {((MenuSelection)i).ToString()}");
  }
}

Есть предложения?

Ответы [ 6 ]

0 голосов
/ 29 сентября 2018

Это очень быстро и грязно.Однако у него есть преимущество в том, что вы можете создать любое меню с любым типом enum.

Разделяет слова на основе регистров (верхний / нижний) переходов.Это работает, за исключением вашего MaxMenuSelection.Вместо того, чтобы помещать это в ваш enum, сделайте его функцией шаблона (для типа enum), которая возвращает GetValues ​​(). Length (см. Ниже):

Показанный ниже where равен where T : struct, потому что компиляторЯ использую не поддерживает where T : System.Enum, что было бы намного лучше, но требует новейшего компилятора.

  public static string SeparateWords(string enumName)
  {
      var buffer = new StringBuilder();
      var wasLower = false;
      foreach (var c in enumName)
      {
          if (wasLower && char.IsUpper(c))
          {
              buffer.Append(' ');
          }

          buffer.Append(c);
          wasLower = char.IsLower(c);
      }

      return buffer.ToString();
  }

  public static void DisplayMenu<T>() where T : struct //should be System.Enum if possible
  {
      var enumType = typeof(T);
      var names = Enum.GetNames(enumType);
      var values = Enum.GetValues(enumType) as int[];
      for (var i = 0; i < names.Length; ++i)
      {
          Console.WriteLine($"[{values[i]}] {SeparateWords(names[i])}");
      }
  }

Я получаю этот вывод:

[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
[5] Max Menu Selection

Когда я вызываю это:

 EnumTest.DisplayMenu<MenuSelection>();

И вы можете получить «Макс. Выбор меню», выполнив это:

public static int MaxMenuSelection<T>() where T : struct
{
    return Enum.GetValues(typeof(T)).Length;
}
0 голосов
/ 29 сентября 2018

Почему бы не сделать что-то простое и добавить _ между словами?

Тогда вы можете сделать это:

    enum MenuSelection
    {
        Create_Customer = 1,
        Create_Account = 2,
        Set_Account_Balance = 3,
        Display_Account_Balance = 4,
        Exit = 5,
        MaxMenuSelection = 5,
    }
    public static void Menu()
    {
        for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
        {
            Console.WriteLine($"[{i}] {((MenuSelection)i).ToString().Replace("_"," ")}");
        }
    }

В результате вы получите:

 [1] Create Customer
 [2] Create Account
 [3] Set Account Balance
 [4] Display Account Balance
 [5] Exit
0 голосов
/ 29 сентября 2018

Вы можете сделать это следующим образом

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    enum MenuSelection
    {
        CreateCustomer = 1,
        CreateAccount = 2,
        SetAccountBalance = 3,
        DisplayAccountBalance = 4,
        Exit = 5,
        MaxMenuSelection = 5,
    }

    public static void Main()
    {
        Enum
            .GetNames(typeof(MenuSelection))
            .Select(name => new 
            { 
                name, 
                index = (int)Enum.Parse(typeof(MenuSelection), name, true) 
            })
            .Select(kv => $"[{kv.index}] " + String.Join(" ", SplitByCamelCase(kv.name)))
            .Select(item => 
            {
                Console.WriteLine(item);
                return true;
            })
            .ToList();
    }

    public static bool IsLower(char ch) 
    {
        return ch >= 'a' && ch <= 'z';
    }

    public static string Head(string str)
    {
        return new String(
                    str
                        .Take(1)
                        .Concat(
                            str
                                .Skip(1)
                                .TakeWhile(IsLower)
                        )
                        .ToArray()
                );
    }

    public static string Tail(string str)
    {
        return new String(str.Skip(Head(str).Length).ToArray());
    }

    public static IEnumerable<string> SplitByCamelCase(string str) 
    {
        if (str.Length == 0) 
            return new List<string>();

        return 
            new List<string> 
            { 
                Head(str) 
            }
            .Concat(
                SplitByCamelCase(
                    Tail(str)
                )
            );
    }
}

Результат:

[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
[5] Max Menu Selection

Посмотреть образец онлайн

0 голосов
/ 28 сентября 2018

Вы можете использовать отражение, чтобы получить атрибут Description (или атрибут Display).Здесь я использовал метод расширения, чтобы сделать его немного проще:

class Program
{
    static void Main(string[] args)
    {
        for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
        {
            Console.WriteLine($"[{i}] {((MenuSelection)i).GetEnumDescription()}");
        }

        Console.ReadLine();
    }
}

public static class Extensions
{
    public static string GetEnumDescription(this MenuSelection m)
    {
        FieldInfo fi = m.GetType().GetField(m.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        return attributes != null && attributes.Length > 0 ? attributes[0].Description : m.ToString();
    }
}

public enum MenuSelection
{
    [Description("Create Customer")]
    CreateCustomer = 1,
    [Description("Create Account")]
    CreateAccount = 2,
    [Description("Set Account Balance")]
    SetAccountBalance = 3,
    [Description("Display Account Balance")]
    DisplayAccountBalance = 4,
    Exit = 5,
    MaxMenuSelection = 5,
}

Результат:

[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
0 голосов
/ 28 сентября 2018

Одним из способов является использование атрибута отображения:

enum MenuSelection
{
   [Display(Name = "Create Customer")]
   CreateCustomer = 1,
   [Display(Name = "Create Account")]
   CreateAccount = 2,
   ...
}

Но получить его значение не так просто, как следовало бы.Вы можете найти его в Как получить атрибут отображаемого имени члена Enum с помощью бритвенного кода MVC?

Другой способ, которым я сам использую это - написанная мной функция, которая добавляет пробелперед каждой заглавной буквой:

public static class Exts
{ 
    public static string CapitalSplit(this string x)
    {
         return Regex.Replace(x, "([a-z])([A-Z])", "$1 $2").Trim();
    }
}

Затем вы можете использовать его как:

 for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
 {
     Console.WriteLine($"[{i}] {((MenuSelection)i).ToString().CapitalSplit()}");
 }
0 голосов
/ 28 сентября 2018

Я бы использовал Dictionary, key - это MenuSelection, а value содержит строку отображения вашего клиента.

Dictionary<MenuSelection, string> dict = new Dictionary<MenuSelection, string>();
dict.Add(MenuSelection.CreateCustomer, "Create Customer");
dict.Add(MenuSelection.CreateAccount, "Create Account");
dict.Add(MenuSelection.SetAccountBalance, "Set Account Balance");
dict.Add(MenuSelection.DisplayAccountBalance, "Display Account Balance");
dict.Add(MenuSelection.Exit, "Exit");

string showValue = string.Empty;
for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
{
    if (dict.TryGetValue((MenuSelection)i, out showValue))
    {
        Console.WriteLine($"[{i}] { showValue}");
    }           
}
...