C# 使用用户友好字符串枚举ToString
我的枚举由以下值组成:C# 使用用户友好字符串枚举ToString,c#,enums,tostring,C#,Enums,Tostring,我的枚举由以下值组成: private enum PublishStatusses{ NotCompleted, Completed, Error }; 我希望能够以用户友好的方式输出这些值。 我不需要再次从字符串转换为值 我使用System.ComponentModel命名空间中的属性。只需装饰枚举: private enum PublishStatusValue { [Description("Not Completed")] NotComplete
private enum PublishStatusses{
NotCompleted,
Completed,
Error
};
我希望能够以用户友好的方式输出这些值。我不需要再次从字符串转换为值 我使用System.ComponentModel命名空间中的属性。只需装饰枚举:
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静态字符串GetDescription(此T enumerationValue)
其中T:struct
{
Type Type=enumerationValue.GetType();
如果(!type.IsEnum)
{
抛出新ArgumentException(“EnumerationValue必须是Enum类型”、“EnumerationValue”);
}
//尝试为可能的友好名称查找DescriptionAttribute
//对于枚举
MemberInfo[]MemberInfo=type.GetMember(enumerationValue.ToString());
if(memberInfo!=null&&memberInfo.Length>0)
{
对象[]attrs=memberInfo[0]。GetCustomAttributes(typeof(DescriptionAttribute),false);
如果(属性!=null&&attrs.Length>0)
{
//拉出描述值
返回((DescriptionAttribute)属性[0])。说明;
}
}
//如果没有description属性,只需返回枚举的ToString
返回enumerationValue.ToString();
}
如果您想要完全可定制的产品,请在此处试用我的解决方案:
基本上,本文概述了如何将描述属性附加到每个枚举,并提供了从枚举映射到描述的通用方法。另一篇文章是Java。不能将方法放入C#中的枚举中 就这样做吧:
PublishStatusses status = ...
String s = status.ToString();
public enum Example
{
Example1,
Example2
}
Console.WriteLine(Example.Example1.ToString("g"));
//Outputs: "Example1"
如果要对枚举值使用不同的显示值,可以使用属性和反射。这里最简单的解决方案是使用自定义扩展方法(至少在.NET 3.5中-您可以将其转换为早期框架版本的静态帮助器方法)
这里我假设您想要返回的不是枚举值的实际名称(您只需调用ToString即可获得该名称)。也许我遗漏了什么,但是enum.GetName有什么问题吗
public string GetName(PublishStatusses value)
{
return Enum.GetName(typeof(PublishStatusses), value)
}
编辑:对于用户友好的字符串,您需要通过.resource来完成国际化/本地化,可以说,使用基于枚举键的固定键比使用相同的decorator属性更好。我使用扩展方法来实现这一点:
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!";
}
}
}
关于Ray Booysen,代码中有一个bug: 您需要考虑枚举值上的多个属性
public static string GetDescription<T>(this object 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 && attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault() != null)
{
//Pull out the description value
return ((DescriptionAttribute)attrs.Where(t=>t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
公共静态字符串GetDescription(此对象枚举值)
其中T:struct
{
Type Type=enumerationValue.GetType();
如果(!type.IsEnum)
{
抛出新ArgumentException(“EnumerationValue必须是Enum类型”、“EnumerationValue”);
}
//尝试为可能的友好名称查找DescriptionAttribute
//对于枚举
MemberInfo[]MemberInfo=type.GetMember(enumerationValue.ToString());
if(memberInfo!=null&&memberInfo.Length>0)
{
对象[]attrs=memberInfo[0]。GetCustomAttributes(typeof(DescriptionAttribute),false);
if(attrs!=null&&attrs.Length>0&&attrs.Where(t=>t.GetType()==typeof(DescriptionAttribute)).FirstOrDefault()!=null)
{
//拉出描述值
return((DescriptionAttribute)attrs.Where(t=>t.GetType()==typeof(DescriptionAttribute)).FirstOrDefault()).Description;
}
}
//如果没有description属性,只需返回枚举的ToString
返回enumerationValue.ToString();
这是对Ray Booysen的代码的更新,该代码使用通用的GetCustomAttributes方法和LINQ使事情变得更整洁
/// <summary>
/// Gets the value of the <see cref="T:System.ComponentModel.DescriptionAttribute"/> on an struct, including enums.
/// </summary>
/// <typeparam name="T">The type of the struct.</typeparam>
/// <param name="enumerationValue">A value of type <see cref="T:System.Enum"/></param>
/// <returns>If the struct has a Description attribute, this method returns the description. Otherwise it just calls ToString() on the struct.</returns>
/// <remarks>Based on http://stackoverflow.com/questions/479410/enum-tostring/479417#479417, but useful for any struct.</remarks>
public static string GetDescription<T>(this T enumerationValue) where T : struct
{
return enumerationValue.GetType().GetMember(enumerationValue.ToString())
.SelectMany(mi => mi.GetCustomAttributes<DescriptionAttribute>(false),
(mi, ca) => ca.Description)
.FirstOrDefault() ?? enumerationValue.ToString();
}
//
///获取结构(包括枚举)上的的值。
///
///结构的类型。
///类型值
///如果结构具有Description属性,则此方法返回描述。否则,它只调用结构上的ToString()。
///基于http://stackoverflow.com/questions/479410/enum-tostring/479417#479417,但对任何结构都有用。
公共静态字符串GetDescription(此T enumerationValue),其中T:struct
{
返回enumerationValue.GetType().GetMember(enumerationValue.ToString())
.SelectMany(mi=>mi.GetCustomAttributes(false),
(mi,ca)=>ca.Description)
.FirstOrDefault()??枚举值.ToString();
}
我碰巧是一个VB.NET迷,下面是我的版本,它将DescriptionAttribute方法与扩展方法相结合。首先,结果:
Imports System.ComponentModel ' For <Description>
Module Module1
''' <summary>
''' An Enum type with three values and descriptions
''' </summary>
Public Enum EnumType
<Description("One")>
V1 = 1
' This one has no description
V2 = 2
<Description("Three")>
V3 = 3
End Enum
Sub Main()
' Description method is an extension in EnumExtensions
For Each v As EnumType In [Enum].GetValues(GetType(EnumType))
Console.WriteLine("Enum {0} has value {1} and description {2}",
v,
CInt(v),
v.Description
)
Next
' Output:
' Enum V1 has value 1 and description One
' Enum V2 has value 2 and description V2
' Enum V3 has value 3 and description Three
End Sub
End Module
由于使用反射
查找描述属性的速度很慢,因此查找也会缓存在一个私有的字典
中,该字典会根据需要进行填充
(很抱歉使用VB.NET解决方案-将其转换为C#应该比较困难,而且我的C#对扩展之类的新主题很生疏)我创建了一个反向扩展方法,将描述转换回枚举值:
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");
}
publicstatict-ToEnumValue(此字符串枚举描述),其中T:struct
{
var类型=类型(T);
如果(!type.IsEnum)
抛出新ArgumentException(“ToEnumValue():必须是枚举类型”、“T”);
foreach(System.Enum.GetValues(类型)中的对象值)
if(val.GetDescription()==enumerationDescription)
返回(T)val;
抛出新ArgumentException(“ToEnumValue():枚举的描述无效”+类型名称,“enumerationDescription”);
}
用示例对上述建议进行总结:
namespace EnumExtensions {
using System;
using System.Reflection;
public class TextAttribute : Attribute {
public string Text;
public TextAttribute( string text ) {
Text = text;
}//ctor
}// class TextAttribute
public static class EnumExtender {
public static string ToText( this Enum enumeration ) {
MemberInfo[] memberInfo = enumeration.GetType().GetMember( enumeration.ToString() );
if ( memberInfo != null && memberInfo.Length > 0 ) {
object[] attributes = memberInfo[ 0 ].GetCustomAttributes( typeof(TextAttribute), false );
if ( attributes != null && attributes.Length > 0 ) {
return ( (TextAttribute)attributes[ 0 ] ).Text;
}
}//if
return enumeration.ToString();
}//ToText
}//class EnumExtender
}//namespace
用法:
using System;
using EnumExtensions;
class Program {
public enum Appearance {
[Text( "left-handed" ) ]
Left,
[Text( "right-handed" ) ]
Right,
}//enum
static void Main( string[] args ) {
var appearance = Appearance.Left;
Console.WriteLine( appearance.ToText() );
}//Main
}//class
更简洁的总结:
using System;
using System.Reflection;
public class TextAttribute : Attribute
{
public string Text;
public TextAttribute(string text)
{
Text = text;
}
}
public static class EnumExtender
{
public static string ToText(this Enum enumeration)
{
var memberInfo = enumeration.GetType().GetMember(enumeration.ToString());
if (memberInfo.Length <= 0) return enumeration.ToString();
var attributes = memberInfo[0].GetCustomAttributes(typeof(TextAttribute), false);
return attributes.Length > 0 ? ((TextAttribute)attributes[0]).Text : enumeration.ToString();
}
}
使用系统;
运用系统反思;
公共类TextAttribute:属性
{
公共字符串文本;
公共文本属性(字符串文本)
{
文本=文本;
}
}
公共静态类枚举扩展程序
{
公共静电传感器
using System;
using System.Reflection;
public class TextAttribute : Attribute
{
public string Text;
public TextAttribute(string text)
{
Text = text;
}
}
public static class EnumExtender
{
public static string ToText(this Enum enumeration)
{
var memberInfo = enumeration.GetType().GetMember(enumeration.ToString());
if (memberInfo.Length <= 0) return enumeration.ToString();
var attributes = memberInfo[0].GetCustomAttributes(typeof(TextAttribute), false);
return attributes.Length > 0 ? ((TextAttribute)attributes[0]).Text : enumeration.ToString();
}
}
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());
enum PublishStatusses
{
[Description("Custom description")]
NotCompleted,
AlmostCompleted,
Error
};
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 static string Description(this Enum value)
{
Type type = value.GetType();
List<string> res = new List<string>();
var arrValue = value.ToString().Split(',').Select(v=>v.Trim());
foreach (string strValue in arrValue)
{
MemberInfo[] memberInfo = type.GetMember(strValue);
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0 && attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault() != null)
{
res.Add(((DescriptionAttribute)attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()).Description);
}
else
res.Add(strValue);
}
else
res.Add(strValue);
}
return res.Aggregate((s,v)=>s+", "+v);
}
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;
}
public static string GetUserFriendlyString(this PublishStatusses status)
{
}
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;
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;
}
}
}
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
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;
}
}
}
private enum PublishStatuses{
NotCompleted,
Completed,
Error
};
private static class PublishStatuses{
public static readonly string NotCompleted = "Not Completed";
public static readonly string Completed = "Completed";
public static readonly string Error = "Error";
};
PublishStatuses.NotCompleted; // "Not Completed"
using System;
public class GetNameTest {
enum Colors { Red, Green, Blue, Yellow };
enum Styles { Plaid, Striped, Tartan, Corduroy };
public static void Main() {
Console.WriteLine("The 4th value of the Colors Enum is {0}", Enum.GetName(typeof(Colors), 3));
Console.WriteLine("The 4th value of the Styles Enum is {0}", Enum.GetName(typeof(Styles), 3));
}
}
// The example displays the following output:
// The 4th value of the Colors Enum is Yellow
// The 4th value of the Styles Enum is Corduroy
string res = Regex.Replace(PublishStatusses.NotCompleted, "[A-Z]", " $0").Trim();
enum Status { Success, Fail, Pending }
public class EnumX<T> where T : struct
{
public T Code { get; set; }
public string Description { get; set; }
public EnumX(T code, string desc)
{
if (!typeof(T).IsEnum) throw new NotImplementedException();
Code = code;
Description = desc;
}
public class Helper
{
private List<EnumX<T>> codes;
public Helper(List<EnumX<T>> codes)
{
this.codes = codes;
}
public string GetDescription(T code)
{
EnumX<T> e = codes.Where(c => c.Code.Equals(code)).FirstOrDefault();
return e is null ? "Undefined" : e.Description;
}
}
}
EnumX<Status>.Helper StatusCodes = new EnumX<Status>.Helper(new List<EnumX<Status>>()
{
new EnumX<Status>(Status.Success,"Operation was successful"),
new EnumX<Status>(Status.Fail,"Operation failed"),
new EnumX<Status>(Status.Pending,"Operation not complete. Please wait...")
});
Console.WriteLine(StatusCodes.GetDescription(Status.Pending));
public enum Example
{
Example1,
Example2
}
Console.WriteLine(Example.Example1.ToString("g"));
//Outputs: "Example1"