Как мне связать связанный с enum combobox с настраиваемым форматированием строк для значений перечисления?
В сообщении Enum ToString описан способ использования пользовательского атрибута DescriptionAttribute
следующим образом:
Enum HowNice {
[Description("Really Nice")]
ReallyNice,
[Description("Kinda Nice")]
SortOfNice,
[Description("Not Nice At All")]
NotNice
}
И затем вы вызываете функцию GetDescription
, используя синтаксис вроде:
GetDescription<HowNice>(NotNice); // Returns "Not Nice At All"
Но это действительно не помогает мне , когда я хочу просто заполнить ComboBox значениями enum, поскольку я не могу заставить ComboBox вызывать GetDescription
.
Я хочу иметь следующие требования:
- Чтение
(HowNice)myComboBox.selectedItem
вернет выбранное значение в качестве значения перечисления.
- Пользователь должен увидеть удобные для пользователя строки отображения, а не только имя значений перечисления. Поэтому вместо того, чтобы видеть "
NotNice
", пользователь увидит "Not Nice At All
".
- Надеемся, что решение потребует минимальных изменений кода для существующих перечислений.
Очевидно, я мог бы реализовать новый класс для каждого перечисления, который я создаю, и переопределить его ToString()
, но это много работы для каждого перечисления, и я бы предпочел избежать этого.
Любые идеи?
Черт, я даже закрою объятие в качестве награды: -)
Ответы
Ответ 1
Вы можете написать TypeConverter, который считывает указанные атрибуты, чтобы просмотреть их в ваших ресурсах. Таким образом, вы получите многоязычную поддержку для отображения имен без особых хлопот.
Посмотрите на методы конвертации TypeConverter ConvertFrom/ConvertTo и используйте отражение для чтения атрибутов в своих полях перечисления.
Ответ 2
ComboBox
есть все, что вам нужно: свойство FormattingEnabled
, которое вы должны установить в true
и Format
событие, где вам нужно будет поместить нужную логику форматирования. Таким образом,
myComboBox.FormattingEnabled = true;
myComboBox.Format += delegate(object sender, ListControlConvertEventArgs e)
{
e.Value = GetDescription<HowNice>((HowNice)e.Value);
}
Ответ 3
Не надо! Перечисления - это примитивы, а не объекты пользовательского интерфейса, что делает их доступными для пользовательского интерфейса в .ToString() с точки зрения дизайна. Вы пытаетесь решить неправильную проблему здесь: реальная проблема заключается в том, что вы не хотите, чтобы Enum.ToString() отображался в поле со списком!
Теперь это очень решаемая проблема! Вы создаете объект пользовательского интерфейса для представления ваших элементов со списком:
sealed class NicenessComboBoxItem
{
public string Description { get { return ...; } }
public HowNice Value { get; private set; }
public NicenessComboBoxItem(HowNice howNice) { Value = howNice; }
}
А затем просто добавьте экземпляры этого класса в свой сборник "Коллекция предметов" и установите следующие свойства:
comboBox.ValueMember = "Value";
comboBox.DisplayMember = "Description";
Ответ 4
TypeConverter. Я думаю, что это то, что я искал. Все приветствуют Саймон Свенссон!
[TypeConverter(typeof(EnumToStringUsingDescription))]
Enum HowNice {
[Description("Really Nice")]
ReallyNice,
[Description("Kinda Nice")]
SortOfNice,
[Description("Not Nice At All")]
NotNice
}
Все, что мне нужно изменить в моем текущем перечислении, добавляет эту строку перед объявлением.
[TypeConverter(typeof(EnumToStringUsingDescription))]
Как только я это сделаю, любое перечисление будет отображаться с помощью DescriptionAttribute
его полей.
О, а TypeConverter
будет определяться следующим образом:
public class EnumToStringUsingDescription : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return (sourceType.Equals(typeof(Enum)));
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return (destinationType.Equals(typeof(String)));
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (!destinationType.Equals(typeof(String)))
{
throw new ArgumentException("Can only convert to string.", "destinationType");
}
if (!value.GetType().BaseType.Equals(typeof(Enum)))
{
throw new ArgumentException("Can only convert an instance of enum.", "value");
}
string name = value.ToString();
object[] attrs =
value.GetType().GetField(name).GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attrs.Length > 0) ? ((DescriptionAttribute)attrs[0]).Description : name;
}
}
Это помогает мне в моем случае ComboBox, но, очевидно, на самом деле не отменяет ToString()
. Думаю, я соглашусь на это тем временем...
Ответ 5
Используя пример перечисления:
using System.ComponentModel;
Enum HowNice
{
[Description("Really Nice")]
ReallyNice,
[Description("Kinda Nice")]
SortOfNice,
[Description("Not Nice At All")]
NotNice
}
Создать расширение:
public static class EnumExtensions
{
public static string Description(this Enum value)
{
var enumType = value.GetType();
var field = enumType.GetField(value.ToString());
var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute),
false);
return attributes.Length == 0
? value.ToString()
: ((DescriptionAttribute)attributes[0]).Description;
}
}
Затем вы можете использовать что-то вроде следующего:
HowNice myEnum = HowNice.ReallyNice;
string myDesc = myEnum.Description();
Для получения дополнительной информации см. http://www.blackwasp.co.uk/EnumDescription.aspx. Кредит отправляется Richrd Carr для решения
Ответ 6
Вы можете создать общую структуру, которую вы могли бы использовать для всех ваших перечислений с описаниями. При неявных преобразованиях в класс и из него ваши переменные по-прежнему работают как перечисление, за исключением метода ToString:
public struct Described<T> where T : struct {
private T _value;
public Described(T value) {
_value = value;
}
public override string ToString() {
string text = _value.ToString();
object[] attr =
typeof(T).GetField(text)
.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attr.Length == 1) {
text = ((DescriptionAttribute)attr[0]).Description;
}
return text;
}
public static implicit operator Described<T>(T value) {
return new Described<T>(value);
}
public static implicit operator T(Described<T> value) {
return value._value;
}
}
Пример использования:
Described<HowNice> nice = HowNice.ReallyNice;
Console.WriteLine(nice == HowNice.ReallyNice); // writes "True"
Console.WriteLine(nice); // writes "Really Nice"
Ответ 7
Лучший способ сделать это - создать класс.
class EnumWithToString {
private string description;
internal EnumWithToString(string desc){
description = desc;
}
public override string ToString(){
return description;
}
}
class HowNice : EnumWithToString {
private HowNice(string desc) : base(desc){}
public static readonly HowNice ReallyNice = new HowNice("Really Nice");
public static readonly HowNice KindaNice = new HowNice("Kinda Nice");
public static readonly HowNice NotVeryNice = new HowNice("Really Mean!");
}
Я считаю, что это лучший способ сделать это.
При добавлении в comboboxes будет отображаться симпатичная ToString, и тот факт, что никто не может делать больше экземпляров вашего класса, по сути делает его перечислением.
p.s. возможно, должны быть некоторые небольшие синтаксические исправления, я не очень хорошо разбираюсь в С#. (Java-парень)
Ответ 8
Я не думаю, что вы можете сделать это без привязки к другому типу - по крайней мере, не удобно. Как правило, даже если вы не можете управлять ToString()
, вы можете использовать TypeConverter
для пользовательского форматирования, но материал IIRC System.ComponentModel
не учитывает это для перечислений.
Вы можете привязать к string[]
описаниям или что-то по существу как пара ключ/значение? (desription/value) - что-то вроде:
class EnumWrapper<T> where T : struct
{
private readonly T value;
public T Value { get { return value; } }
public EnumWrapper(T value) { this.value = value; }
public string Description { get { return GetDescription<T>(value); } }
public override string ToString() { return Description; }
public static EnumWrapper<T>[] GetValues()
{
T[] vals = (T[])Enum.GetValues(typeof(T));
return Array.ConvertAll(vals, v => new EnumWrapper<T>(v));
}
}
И затем привязитесь к EnumWrapper<HowNice>.GetValues()
Ответ 9
Невозможно переопределить ToString() перечислений в С#. Однако вы можете использовать методы расширения;
public static string ToString(this HowNice self, int neverUsed)
{
switch (self)
{
case HowNice.ReallyNice:
return "Rilly, rilly nice";
break;
...
Конечно, вам нужно будет сделать явный вызов метода, т.е.
HowNice.ReallyNice.ToString(0)
Это нехорошее решение, с оператором switch и всем - но оно должно работать и, надеюсь, без изменений для многих переписываемых...
Ответ 10
Учитывая, что вы предпочитаете не создавать класс для каждого перечисления, я бы рекомендовал вместо этого создать словарь значения/отображаемого текста перечисления и привязки.
Обратите внимание, что это имеет зависимость от методов метода GetDescription в исходном сообщении.
public static IDictionary<T, string> GetDescriptions<T>()
where T : struct
{
IDictionary<T, string> values = new Dictionary<T, string>();
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("T must be of Enum type", "enumerationValue");
}
//Tries to find a DescriptionAttribute for a potential friendly name
//for the enum
foreach (T value in Enum.GetValues(typeof(T)))
{
string text = value.GetDescription();
values.Add(value, text);
}
return values;
}
Ответ 11
В ответ на ответ @scraimer, вот версия конвертера типа перечисления в строку, которая также поддерживает флаги:
/// <summary>
/// A drop-in converter that returns the strings from
/// <see cref="System.ComponentModel.DescriptionAttribute"/>
/// of items in an enumaration when they are converted to a string,
/// like in ToString().
/// </summary>
public class EnumToStringUsingDescription : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return (sourceType.Equals(typeof(Enum)));
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return (destinationType.Equals(typeof(String)));
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType.Equals(typeof(String)))
{
string name = value.ToString();
Type effectiveType = value.GetType();
if (name != null)
{
FieldInfo fi = effectiveType.GetField(name);
if (fi != null)
{
object[] attrs =
fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attrs.Length > 0) ? ((DescriptionAttribute)attrs[0]).Description : name;
}
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
/// <summary>
/// Coverts an Enums to string by it description. falls back to ToString.
/// </summary>
/// <param name="value">The value.</param>
/// <returns></returns>
public string EnumToString(Enum value)
{
//getting the actual values
List<Enum> values = EnumToStringUsingDescription.GetFlaggedValues(value);
//values.ToString();
//Will hold results for each value
List<string> results = new List<string>();
//getting the representing strings
foreach (Enum currValue in values)
{
string currresult = this.ConvertTo(null, null, currValue, typeof(String)).ToString();;
results.Add(currresult);
}
return String.Join("\n",results);
}
/// <summary>
/// All of the values of enumeration that are represented by specified value.
/// If it is not a flag, the value will be the only value retured
/// </summary>
/// <param name="value">The value.</param>
/// <returns></returns>
private static List<Enum> GetFlaggedValues(Enum value)
{
//checking if this string is a flaged Enum
Type enumType = value.GetType();
object[] attributes = enumType.GetCustomAttributes(true);
bool hasFlags = false;
foreach (object currAttibute in attributes)
{
if (enumType.GetCustomAttributes(true)[0] is System.FlagsAttribute)
{
hasFlags = true;
break;
}
}
//If it is a flag, add all fllaged values
List<Enum> values = new List<Enum>();
if (hasFlags)
{
Array allValues = Enum.GetValues(enumType);
foreach (Enum currValue in allValues)
{
if (value.HasFlag(currValue))
{
values.Add(currValue);
}
}
}
else//if not just add current value
{
values.Add(value);
}
return values;
}
}
И метод расширения для его использования:
/// <summary>
/// Converts an Enum to string by it description. falls back to ToString
/// </summary>
/// <param name="enumVal">The enum val.</param>
/// <returns></returns>
public static string ToStringByDescription(this Enum enumVal)
{
EnumToStringUsingDescription inter = new EnumToStringUsingDescription();
string str = inter.EnumToString(enumVal);
return str;
}
Ответ 12
Создайте коллекцию, в которой содержится то, что вам нужно (например, простые объекты, содержащие свойство Value
, содержащее значение enum HowNice
и свойство Description
, содержащее GetDescription<HowNice>(Value)
и привязку данных к этой коллекции.
Бит выглядит следующим образом:
Combo.DataSource = new EnumeratedValueCollection<HowNice>();
Combo.ValueMember = "Value";
Combo.DisplayMember = "Description";
когда у вас есть такой класс коллекции:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Whatever.Tickles.Your.Fancy
{
public class EnumeratedValueCollection<T> : ReadOnlyCollection<EnumeratedValue<T>>
{
public EnumeratedValueCollection()
: base(ListConstructor()) { }
public EnumeratedValueCollection(Func<T, bool> selection)
: base(ListConstructor(selection)) { }
public EnumeratedValueCollection(Func<T, string> format)
: base(ListConstructor(format)) { }
public EnumeratedValueCollection(Func<T, bool> selection, Func<T, string> format)
: base(ListConstructor(selection, format)) { }
internal EnumeratedValueCollection(IList<EnumeratedValue<T>> data)
: base(data) { }
internal static List<EnumeratedValue<T>> ListConstructor()
{
return ListConstructor(null, null);
}
internal static List<EnumeratedValue<T>> ListConstructor(Func<T, string> format)
{
return ListConstructor(null, format);
}
internal static List<EnumeratedValue<T>> ListConstructor(Func<T, bool> selection)
{
return ListConstructor(selection, null);
}
internal static List<EnumeratedValue<T>> ListConstructor(Func<T, bool> selection, Func<T, string> format)
{
if (null == selection) selection = (x => true);
if (null == format) format = (x => GetDescription<T>(x));
var result = new List<EnumeratedValue<T>>();
foreach (T value in System.Enum.GetValues(typeof(T)))
{
if (selection(value))
{
string description = format(value);
result.Add(new EnumeratedValue<T>(value, description));
}
}
return result;
}
public bool Contains(T value)
{
return (Items.FirstOrDefault(item => item.Value.Equals(value)) != null);
}
public EnumeratedValue<T> this[T value]
{
get
{
return Items.First(item => item.Value.Equals(value));
}
}
public string Describe(T value)
{
return this[value].Description;
}
}
[System.Diagnostics.DebuggerDisplay("{Value} ({Description})")]
public class EnumeratedValue<T>
{
private T value;
private string description;
internal EnumeratedValue(T value, string description) {
this.value = value;
this.description = description;
}
public T Value { get { return this.value; } }
public string Description { get { return this.description; } }
}
}
Как вы можете видеть, эта коллекция легко настраивается с помощью лямбда, чтобы выбрать подмножество вашего перечислителя и/или реализовать настраиваемое форматирование до string
вместо использования функции GetDescription<T>(x)
, которую вы упоминаете.
Ответ 13
Я бы написал общий класс для использования с любым типом. Я использовал что-то вроде этого в прошлом:
public class ComboBoxItem<T>
{
/// The text to display.
private string text = "";
/// The associated tag.
private T tag = default(T);
public string Text
{
get
{
return text;
}
}
public T Tag
{
get
{
return tag;
}
}
public override string ToString()
{
return text;
}
// Add various constructors here to fit your needs
}
Кроме того, вы можете добавить статический метод "factory", чтобы создать список элементов combobox с учетом типа перечисления (в значительной степени аналогично методу GetDescriptions, который у вас есть). Это избавит вас от необходимости реализовать один объект для каждого типа перечисления, а также обеспечить хорошее/логическое место для вспомогательного метода GetDescriptions (лично я бы назвал его FromEnum (T obj)...
Ответ 14
Вы можете использовать PostSharp для таргетинга Enum.ToString и добавить дополнительный код, который вы хотите.
Это не требует каких-либо изменений кода.
Ответ 15
Вам нужно преобразовать enum в ReadonlyCollection и привязать коллекцию к combobox (или любому элементу управления, поддерживающему значение Key-Value Pair).
Сначала вам нужен класс, чтобы содержать элементы списка. Поскольку все, что вам нужно, это пара int/string, я предлагаю использовать интерфейс и комбо базового класса, чтобы вы могли реализовать функциональность любого объекта, который вы хотите:
public interface IValueDescritionItem
{
int Value { get; set;}
string Description { get; set;}
}
public class MyItem : IValueDescritionItem
{
HowNice _howNice;
string _description;
public MyItem()
{
}
public MyItem(HowNice howNice, string howNice_descr)
{
_howNice = howNice;
_description = howNice_descr;
}
public HowNice Niceness { get { return _howNice; } }
public String NicenessDescription { get { return _description; } }
#region IValueDescritionItem Members
int IValueDescritionItem.Value
{
get { return (int)_howNice; }
set { _howNice = (HowNice)value; }
}
string IValueDescritionItem.Description
{
get { return _description; }
set { _description = value; }
}
#endregion
}
Вот интерфейс и класс класса, который его реализует. Обратите внимание, что класс "Key" строго типизирован для Enum и что свойства IValueDescritionItem реализованы явно (так что класс может иметь любые свойства, и вы можете ВЫБРАТЬ те из них которые реализуют пару Key/Value.
Теперь класс EnumToReadOnlyCollection:
public class EnumToReadOnlyCollection<T,TEnum> : ReadOnlyCollection<T> where T: IValueDescritionItem,new() where TEnum : struct
{
Type _type;
public EnumToReadOnlyCollection() : base(new List<T>())
{
_type = typeof(TEnum);
if (_type.IsEnum)
{
FieldInfo[] fields = _type.GetFields();
foreach (FieldInfo enum_item in fields)
{
if (!enum_item.IsSpecialName)
{
T item = new T();
item.Value = (int)enum_item.GetValue(null);
item.Description = ((ItemDescription)enum_item.GetCustomAttributes(false)[0]).Description;
//above line should be replaced with proper code that gets the description attribute
Items.Add(item);
}
}
}
else
throw new Exception("Only enum types are supported.");
}
public T this[TEnum key]
{
get
{
return Items[Convert.ToInt32(key)];
}
}
}
Итак, все, что вам нужно в вашем коде:
private EnumToReadOnlyCollection<MyItem, HowNice> enumcol;
enumcol = new EnumToReadOnlyCollection<MyItem, HowNice>();
comboBox1.ValueMember = "Niceness";
comboBox1.DisplayMember = "NicenessDescription";
comboBox1.DataSource = enumcol;
Помните, что ваша коллекция напечатана с помощью MyItem, поэтому значение combobox должно возвращать значение перечисления, если вы привязываетесь к соответствующему proprtie.
Я добавил свойство T этого [Enum t], чтобы сделать коллекцию еще более полезной, чем простое комбо, например textBox1.Text = enumcol [HowNice.ReallyNice].NicenessDescription;
Вы можете, конечно, выбрать MyItem в класс Key/Value, используемый только для этого puprose, который эффективно пропускает MyItem в аргументах типа EnumToReadnlyCollection в целом, но тогда вы будете вынуждены пойти с int для ключа (что означает получение combobox1.SelectedValue вернет int, а не тип перечисления). Вы обходите это, если вы создаете класс KeyValueItem для замены MyItem и т.д. И т.д....
Ответ 16
Извините за то, что вы добавили эту старую нить.
Я бы сделал следующий путь для локализации перечисления, так как он может отображать значимые и локализованные значения для пользователя, а не просто для описания, через текстовое поле выпадающего списка в этом примере.
Сначала я создаю простой метод под названием OwToStringByCulture для получения локализованных строк из файла глобальных ресурсов, в этом примере это BiBongNet.resx в папке App_GlobalResources. Внутри этого файла ресурсов убедитесь, что все строки совпадают с значениями перечисления (ReallyNice, SortOfNice, NotNice). В этом методе я передаю параметр: resourceClassName, который обычно является именем файла ресурсов.
Затем я создаю статический метод, чтобы заполнить выпадающий список с перечислением как его источником данных, называемым OwFillDataWithEnum. Этот метод можно использовать с любым перечислением позже.
Затем на странице с выпадающим списком, названным DropDownList1, я установил в Page_Load следующую только одну простую строку кода, чтобы заполнить перечисление в раскрывающемся списке.
BiBongNet.OwFillDataWithEnum<HowNice>(DropDownList1, "BiBongNet");
Что это. Я думаю, что с помощью некоторых простых методов, таких как эти, вы можете заполнить любой элемент управления списком любым перечислением, причем не только как описательные значения, но и локализованный текст для отображения. Вы можете использовать все эти методы в качестве методов расширения для лучшего использования.
Надеюсь на эту помощь.
Поделиться, чтобы получить общий доступ!
Вот методы:
public class BiBongNet
{
enum HowNice
{
ReallyNice,
SortOfNice,
NotNice
}
/// <summary>
/// This method is for filling a listcontrol,
/// such as dropdownlist, listbox...
/// with an enum as the datasource.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="ctrl"></param>
/// <param name="resourceClassName"></param>
public static void OwFillDataWithEnum<T>(ListControl ctrl, string resourceClassName)
{
var owType = typeof(T);
var values = Enum.GetValues(owType);
for (var i = 0; i < values.Length; i++)
{
//Localize this for displaying listcontrol text field.
var text = OwToStringByCulture(resourceClassName, Enum.Parse(owType, values.GetValue(i).ToString()).ToString());
//This is for listcontrol value field
var key = (Enum.Parse(owType, values.GetValue(i).ToString()));
//add values of enum to listcontrol.
ctrl.Items.Add(new ListItem(text, key.ToString()));
}
}
/// <summary>
/// Get localized strings.
/// </summary>
/// <param name="resourceClassName"></param>
/// <param name="resourceKey"></param>
/// <returns></returns>
public static string OwToStringByCulture(string resourceClassName, string resourceKey)
{
return (string)HttpContext.GetGlobalResourceObject(resourceClassName, resourceKey);
}
}
Ответ 17
Enum HowNice {
[Description("Really Nice")]
ReallyNice,
[Description("Kinda Nice")]
SortOfNice,
[Description("Not Nice At All")]
NotNice
}
Чтобы решить эту проблему, вы должны использовать метод расширения и массив строк как:
Enum HowNice {
ReallyNice = 0,
SortOfNice = 1,
NotNice = 2
}
internal static class HowNiceIsThis
{
const String[] strings = { "Really Nice", "Kinda Nice", "Not Nice At All" }
public static String DecodeToString(this HowNice howNice)
{
return strings[(int)howNice];
}
}
Простой код и быстрое декодирование.
Ответ 18
Я пробовал этот подход, и это сработало для меня.
Я создал класс оболочки для перечислений и перегрузил неявный оператор, чтобы я мог назначить его переменным перечисления (в моем случае мне пришлось привязать объект к значению ComboBox
).
Вы можете использовать отражение для форматирования значений перечисления так, как вы хотите, в моем случае я извлекаю DisplayAttribute
из значений перечисления (если они существуют).
Надеюсь, что это поможет.
public sealed class EnumItem<T>
{
T value;
public override string ToString()
{
return Display;
}
public string Display { get; private set; }
public T Value { get; set; }
public EnumItem(T val)
{
value = val;
Type en = val.GetType();
MemberInfo res = en.GetMember(val.ToString())?.FirstOrDefault();
DisplayAttribute display = res.GetCustomAttribute<DisplayAttribute>();
Display = display != null ? String.Format(display.Name, val) : val.ToString();
}
public static implicit operator T(EnumItem<T> val)
{
return val.Value;
}
public static implicit operator EnumItem<T>(T val)
{
return new EnumItem<T>(val);
}
}
EDIT:
На всякий случай, я использую следующую функцию для получения значений enum
, которые я использую для DataSource
ComboBox
public static class Utils
{
public static IEnumerable<EnumItem<T>> GetEnumValues<T>()
{
List<EnumItem<T>> result = new List<EnumItem<T>>();
foreach (T item in Enum.GetValues(typeof(T)))
{
result.Add(item);
}
return result;
}
}
Ответ 19
Как только у вас есть метод GetDescription
(он должен быть глобальным статическим), вы можете использовать его с помощью метода расширения:
public static string ToString(this HowNice self)
{
return GetDescription<HowNice>(self);
}
Ответ 20
Enum HowNice {
[StringValue("Really Nice")]
ReallyNice,
[StringValue("Kinda Nice")]
SortOfNice,
[StringValue("Not Nice At All")]
NotNice
}
Status = ReallyNice.GetDescription()
Ответ 21
Вы можете определить Enum как
Enum HowNice {
[StringValue("Really Nice")]
ReallyNice,
[StringValue("Kinda Nice")]
SortOfNice,
[StringValue("Not Nice At All")]
NotNice
}
а затем используйте HowNice.GetStringValue()
.