我的枚举包含以下值:
private enum PublishStatusses{
NotCompleted,
Completed,
Error
};
我希望能以用户友好的方式输出这些值。
但我不需要再将字符串转换回值。
我使用来自 System.ComponentModel 命名空间的 Description
属性。只需装饰枚举:
private enum PublishStatusValue
{
[Description("Not Completed")]
NotCompleted,
Completed,
Error
};
然后使用以下代码来检索它:
public static string GetDescription<T>(this T enumerationValue)
where T : struct
{
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}
//Tries to find a DescriptionAttribute for a potential friendly name
//for the enum
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attrs[0]).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
}
我使用扩展方法来实现这个:
public enum ErrorLevel
{
None,
Low,
High,
SoylentGreen
}
public static class ErrorLevelExtensions
{
public static string ToFriendlyString(this ErrorLevel me)
{
switch(me)
{
case ErrorLevel.None:
return "Everything is OK";
case ErrorLevel.Low:
return "SNAFU, if you know what I mean.";
case ErrorLevel.High:
return "Reaching TARFU levels";
case ErrorLevel.SoylentGreen:
return "ITS PEOPLE!!!!";
default:
return "Get your damn dirty hands off me you FILTHY APE!";
}
}
}
default
分支的实现返回me.ToString()
,并且只为你想要覆盖的枚举值提供switch case语句。在你的例子中,我知道它们都是不同的,但在实际应用中,我认为大多数单词枚举值就足够了,你只需要为多个单词的枚举值提供覆盖。 - Scottpublic string GetName(PublishStatusses value)
{
return Enum.GetName(typeof(PublishStatusses), value)
}
编辑:要创建用户友好的字符串,您需要通过 .resource 进行国际化/本地化处理,使用基于枚举键的固定键比在相同属性上使用装饰器属性更好。
public static T ToEnumValue<T>(this string enumerationDescription) where T : struct
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException("ToEnumValue<T>(): Must be of enum type", "T");
foreach (object val in System.Enum.GetValues(type))
if (val.GetDescription<T>() == enumerationDescription)
return (T)val;
throw new ArgumentException("ToEnumValue<T>(): Invalid description for enum " + type.Name, "enumerationDescription");
}
最简单的解决方法是使用自定义扩展方法(至少在.NET 3.5中 - 您可以将其转换为早期框架版本的静态帮助器方法)。
public static string ToCustomString(this PublishStatusses value)
{
switch(value)
{
// Return string depending on value.
}
return null;
}
我在这里假设你想返回枚举值的实际名称之外的其他内容(你可以通过简单地调用ToString来获取它)。
那篇帖子是关于Java的。在C#中,您无法将方法放入枚举中。
只需像这样做:
PublishStatusses status = ...
String s = status.ToString();
如果你想为枚举值使用不同的显示值,你可以使用属性和反射。
还有一些更原始的选项,可以避免使用类/引用类型:
数组方法
private struct PublishStatusses
{
public static string[] Desc = {
"Not Completed",
"Completed",
"Error"
};
public enum Id
{
NotCompleted = 0,
Completed,
Error
};
}
用法
string desc = PublishStatusses.Desc[(int)PublishStatusses.Id.Completed];
嵌套结构体方法
private struct PublishStatusses
{
public struct NotCompleted
{
public const int Id = 0;
public const string Desc = "Not Completed";
}
public struct Completed
{
public const int Id = 1;
public const string Desc = "Completed";
}
public struct Error
{
public const int Id = 2;
public const string Desc = "Error";
}
}
用法
int id = PublishStatusses.NotCompleted.Id;
string desc = PublishStatusses.NotCompleted.Desc;
更新(2018年03月09日)
一种扩展方法和上面第一种技术的混合体。
我更喜欢将枚举定义在它们“属于”的地方(靠近它们来源的地方,而不是在某个通用的全局命名空间中)。
namespace ViewModels
{
public class RecordVM
{
//public enum Enum { Minutes, Hours }
public struct Enum
{
public enum Id { Minutes, Hours }
public static string[] Name = { "Minute(s)", "Hour(s)" };
}
}
}
扩展方法似乎适用于常见领域,而枚举的“本地化”定义现在使扩展方法更加冗长。
namespace Common
{
public static class EnumExtensions
{
public static string Name(this RecordVM.Enum.Id id)
{
return RecordVM.Enum.Name[(int)id];
}
}
}
枚举及其扩展方法的使用示例。
namespace Views
{
public class RecordView
{
private RecordDataFieldList<string, string> _fieldUnit;
public RecordView()
{
_fieldUnit.List = new IdValueList<string, string>
{
new ListItem<string>((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()),
new ListItem<string>((int)RecordVM.Enum.Id.Hours, RecordVM.Enum.Id.Hours.Name())
};
}
private void Update()
{
RecordVM.Enum.Id eId = DetermineUnit();
_fieldUnit.Input.Text = _fieldUnit.List.SetSelected((int)eId).Value;
}
}
}
注意:我实际上决定取消Enum
包装器(和Name
数组),因为最好的方式是将名称字符串来自于资源(即配置文件或数据库)而不是硬编码,并且因为我最终将扩展方法放在ViewModels
命名空间中(只是在不同的“CommonVM.cs”文件中)。再加上整个.Id
的事情变得令人分心和繁琐。namespace ViewModels
{
public class RecordVM
{
public enum Enum { Minutes, Hours }
//public struct Enum
//{
// public enum Id { Minutes, Hours }
// public static string[] Name = { "Minute(s)", "Hour(s)" };
//}
}
}
CommonVM.cs
//namespace Common
namespace ViewModels
{
public static class EnumExtensions
{
public static string Name(this RecordVM.Enum id)
{
//return RecordVM.Enum.Name[(int)id];
switch (id)
{
case RecordVM.Enum.Minutes: return "Minute(s)";
case RecordVM.Enum.Hours: return "Hour(s)";
default: return null;
}
}
}
}
枚举类型和其扩展方法的用法示例。
namespace Views
{
public class RecordView
{
private RecordDataFieldList<string, string> _fieldUnit
public RecordView()
{
_fieldUnit.List = new IdValueList<string, string>
{
new ListItem<string>((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()),
new ListItem<string>((int)RecordVM.Enum.Id.Hours, RecordVM.Enum.Id.Hours.Name())
};
}
private void Update()
{
RecordVM.Enum eId = DetermineUnit();
_fieldUnit.Input.Text = _fieldUnit.List.SetSelected((int)eId).Value;
}
}
}
最简单的方法就是将此扩展类包含在您的项目中,它可以与项目中的任何枚举一起使用:
public static class EnumExtensions
{
public static string ToFriendlyString(this Enum code)
{
return Enum.GetName(code.GetType(), code);
}
}
使用方法:
enum ExampleEnum
{
Demo = 0,
Test = 1,
Live = 2
}
...
ExampleEnum ee = ExampleEnum.Live;
Console.WriteLine(ee.ToFriendlyString());
string result = "Result: " + ee;
- John您可以使用Humanizer软件包,具有枚举人类化的可能性。一个例子:
enum PublishStatusses
{
[Description("Custom description")]
NotCompleted,
AlmostCompleted,
Error
};
然后您可以直接在枚举上使用Humanize
扩展方法:
var st1 = PublishStatusses.NotCompleted;
var str1 = st1.Humanize(); // will result in Custom description
var st2 = PublishStatusses.AlmostCompleted;
var str2 = st2.Humanize(); // will result in Almost completed (calculated automaticaly)
public enum MyEnum
{
[Description("Option One")]
Option_One
}
public static string ToDescriptionString(this Enum This)
{
Type type = This.GetType();
string name = Enum.GetName(type, This);
MemberInfo member = type.GetMembers()
.Where(w => w.Name == name)
.FirstOrDefault();
DescriptionAttribute attribute = member != null
? member.GetCustomAttributes(true)
.Where(w => w.GetType() == typeof(DescriptionAttribute))
.FirstOrDefault() as DescriptionAttribute
: null;
return attribute != null ? attribute.Description : name;
}
this
参数,在许多网络示例中可以看到其被称为 This
。像您所做的那样将其类型作为调用方式 (Enum Enum
) 会使代码不够易读。 - Massimiliano Kraus