2015-01-18 3 views
2

У меня есть перечисление, который я хочу представить в виде строки, используя особый способ:Преобразование перечисления в строку, имея место

public enum FailureDescription 
{ 
    MemoryFailure, 
    Fragmentation, 
    SegmentationFault 
} 

Я хочу напечатать значение этого перечисления следующим образом: FailureDescription.MemoryFailure.ToString() - > Memory Failure Могу ли я сделать это ? Как? Внедрить ToString?

+0

Как я знаю ToSttring работает по умолчанию перечислений .: http://msdn.microsoft. com/en-us/library/a0h36syw% 28v = vs.110% 29.aspx –

+0

Используйте атрибут [Flags] – Sam

+0

@ LóriNóda - да. Как добавить пробелы? – Yakov

ответ

2

Вы можете написать собственный метод расширения:

public static string ToFormattedText(this MyEnum value) 
{ 
    var stringVal = value.ToString(); 
    var bld = new StringBuilder(); 

    for (var i = 1; i < stringVal.Length; i++) 
    { 
     if (char.IsUpper(stringVal[i])) 
     { 
      bld.Append(" "); 
     } 

     bld.Append(stringVal[i]); 
    } 

    return bld.ToString(); 
} 

Если вы хотите метод, доступный для всех перечислений, просто замените MyEnum с Enum.

Использование:

var test = MyEnum.SampleName.ToFormattedText(); 

Рассмотрим кэширование - построение строки каждый раз не может быть эффективным.

+0

Я вижу. Благодарю. Я хотел больше встроенного способа. – Yakov

+0

нет встроенный способ. вы не можете переопределить ToString перечисления. –

+0

Нет встроенных способов добавления пространств таким образом. Почему предлагаемое решение не может быть использовано? –

0

Вы также можете использовать простой регулярок & LinQ смесь для извлечения и сцепить слова:

var withSpaces = 
    Regex 
    .Matches(
     FailureDescription.MemoryFailureTest.ToString(), 
     @"([A-Z][a-z]+)(?=[A-Z]|$)") 
    .Cast<Match>() 
    .Select(m => m.Groups[1].Value) 
    .Aggregate((str, next) => (str = str + " " + next)); 

DEMO at ideone.com

где:

([A-Z][a-z]+)(?=[A-Z]|$) 

спички слова, которые начинаются с верхней в виде букв до следующей верхней буквы или конца строки: DEMO at regex101

.Select(m => m.Groups[1].Value) 

выбирает совпавшие значения из группы 1

.Aggregate((str, next) => (str = str + " " + next)); 

сцепляет слова и вставляет пробел между ними.

0

Используйте атрибут Description, чтобы декодировать ваши значения перечисления. Я бы предложил добавить файл resx для ресурсов, чтобы вы могли легче локализовать. Если вы жестко закодировали «Ошибка памяти», становится больше работы, чтобы иметь возможность изменить это на другой язык (как упоминал Ханс Пассант в комментариях).

public enum FailureDescription 
{ 
    [Description("Memory Failure")] //hardcoding English 
    MemoryFailure, 
    [Description(MyStringsResourceFile.FragmentationDescription)] //reading from a resx file makes localisation easier 
    Fragmentation, 
    [Description(MyStringsResourceFile.SegmentationFaultDescription)] 
    SegmentationFault 
} 

Вы можете создать метод, или метод расширения (как показано) для чтения значения Description.

public static class Extensions 
{ 
    public static string GetDescription(this Enum value) 
    { 

     FieldInfo fi = value.GetType().GetField(value.ToString()); 

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

     if (attributes != null && 
      attributes.Length > 0) 
      return attributes[0].Description; 
     else 
      return value.ToString(); 
    } 
} 

Затем вызовите метод как так

Console.WriteLine(FailureDescription.MemoryFailure.GetDescription()); 
+0

... если только файлы' resx' были не так уж плохи для поддержания, -] – t3chb0t

+0

Ха-ха, не самая забавная часть локализации – keyboardP

0

Вот одна из утилит я использую. @HansPassant в своем комментарии поднял хороший момент о локализации.

Этот код принимает во внимание файлы ресурсов. В атрибуте с двумя параметрами first param является файлом Key in Resource, где вторым параметром является пространство имен для ресурса.

заказ мерзавец репо https://github.com/seanpaul/EnumExtensions

public enum TestEnum 
{ 
    //You can pass what ever string value you want 
    [StringValue("From Attribute")] 
    FromAttribute = 1, 

    //If localizing, you can use resource files 
    //First param is Key in resource file, second is namespace for Resources. 
    [StringValue("Test", "EnumExtensions.Tests.Resources")] 
    FromResource = 2, 

    //or don't mention anything and it will use built-in ToString 
    BuiltInToString = 3 
} 

[Test()] 
public void GetValueFromAttribute() 
{ 
    var testEnum = TestEnum.FromAttribute; 
    Assert.AreEqual ("From Attribute", testEnum.GetStringValue()); 
} 
[Test()] 
public void GetValueFromResourceFile() 
{ 
    var testEnum = TestEnum.FromResource; 
    Assert.AreEqual ("From Resource File", testEnum.GetStringValue()); 
} 
0

Этот метод расширения будет делать это для вас:

public static string ToFormattedText(this FailureDescription value) 
{ 
    return new string(value.ToString() 
     .SelectMany(c => 
      char.IsUpper(c) 
      ? new [] { ' ', c } 
      : new [] { c }) 
     .ToArray()).Trim(); 
}