我有以下列举:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
然而问题是,当我请求AuthenticationMethod时,我需要“FORMS”这个词。表单而不是id
对于这个问题,我找到了以下解决方案(链接):
首先,我需要创建一个自定义属性“StringValue”:
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
然后我可以将这个属性添加到我的枚举器中:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
当然,我需要一些东西来检索StringValue:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
很好,现在我已经有了工具来获取枚举器的字符串值。
然后我可以这样使用它:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
好的,现在所有这些工作就像一个魅力,但我发现它有很多工作。我想知道有没有更好的解决办法。
我还尝试了一些字典和静态属性,但这也不是更好。
我的答案是,正在处理@user29964的答案(这是迄今为止最简单和最接近Enum的答案)
public class StringValue : System.Attribute
{
private string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
public static string GetStringValue(Enum Flagvalue)
{
Type type = Flagvalue.GetType();
string[] flags = Flagvalue.ToString().Split(',').Select(x => x.Trim()).ToArray();
List<string> values = new List<string>();
for (int i = 0; i < flags.Length; i++)
{
FieldInfo fi = type.GetField(flags[i].ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
values.Add(attrs[0].Value);
}
}
return String.Join(",", values);
}
使用
[Flags]
public enum CompeteMetric
{
/// <summary>
/// u
/// </summary>
[StringValue("u")]//Json mapping
Basic_UniqueVisitors = 1 //Basic
,
/// <summary>
/// vi
/// </summary>
[StringValue("vi")]//json mapping
Basic_Visits = 2// Basic
,
/// <summary>
/// rank
/// </summary>
[StringValue("rank")]//json mapping
Basic_Rank = 4//Basic
}
例子
CompeteMetric metrics = CompeteMetric.Basic_Visits | CompeteMetric.Basic_Rank;
string strmetrics = StringValue.GetStringValue(metrics);
它会返回
“vi,排名”
更新:访问这个页面,8年后,在很长一段时间没有接触c#之后,看起来我的答案不再是最好的解决方案。我非常喜欢与属性-函数绑定的转换器解决方案。
如果你正在阅读这篇文章,请确保你也查看了其他答案。(提示:它们在这个上面)
和你们大多数人一样,我非常喜欢Jakub Šturc所选的答案,但我也非常讨厌复制粘贴代码,并尽可能少地这样做。
因此,我决定使用一个EnumBase类,从其中继承/内置大部分功能,从而使我能够专注于内容而不是行为。
这种方法的主要问题是基于这样一个事实,即尽管Enum值是类型安全的实例,但交互是与Enum Class类型的静态实现进行的。
所以在泛型魔法的帮助下,我想我终于得到了正确的组合。
希望有人能像我一样觉得这个有用。
我将从Jakub的例子开始,但是使用继承和泛型:
public sealed class AuthenticationMethod : EnumBase<AuthenticationMethod, int>
{
public static readonly AuthenticationMethod FORMS =
new AuthenticationMethod(1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION =
new AuthenticationMethod(2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON =
new AuthenticationMethod(3, "SSN");
private AuthenticationMethod(int Value, String Name)
: base( Value, Name ) { }
public new static IEnumerable<AuthenticationMethod> All
{ get { return EnumBase<AuthenticationMethod, int>.All; } }
public static explicit operator AuthenticationMethod(string str)
{ return Parse(str); }
}
这里是基类:
using System;
using System.Collections.Generic;
using System.Linq; // for the .AsEnumerable() method call
// E is the derived type-safe-enum class
// - this allows all static members to be truly unique to the specific
// derived class
public class EnumBase<E, T> where E: EnumBase<E, T>
{
#region Instance code
public T Value { get; private set; }
public string Name { get; private set; }
protected EnumBase(T EnumValue, string Name)
{
Value = EnumValue;
this.Name = Name;
mapping.Add(Name, this);
}
public override string ToString() { return Name; }
#endregion
#region Static tools
static private readonly Dictionary<string, EnumBase<E, T>> mapping;
static EnumBase() { mapping = new Dictionary<string, EnumBase<E, T>>(); }
protected static E Parse(string name)
{
EnumBase<E, T> result;
if (mapping.TryGetValue(name, out result))
{
return (E)result;
}
throw new InvalidCastException();
}
// This is protected to force the child class to expose it's own static
// method.
// By recreating this static method at the derived class, static
// initialization will be explicit, promising the mapping dictionary
// will never be empty when this method is called.
protected static IEnumerable<E> All
{ get { return mapping.Values.AsEnumerable().Cast<E>(); } }
#endregion
}
我使用系统中的Description属性。ComponentModel名称空间。简单地装饰枚举,然后使用下面的代码来检索它:
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)
{
//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 Cycle : int
{
[Description("Daily Cycle")]
Daily = 1,
Weekly,
Monthly
}
这段代码很好地满足了不需要“友好名称”的枚举,只返回枚举的. tostring()。
我支持Harvey,但不用const。我可以混合匹配字符串,int,等等。
public class xlsLayout
{
public int xlHeaderRow = 1;
public int xlFirstDataRow = 2;
public int xlSkipLinesBetweenFiles = 1; //so 0 would mean don't skip
public string xlFileColumn = "A";
public string xlFieldColumn = "B";
public string xlFreindlyNameColumn = "C";
public string xlHelpTextColumn = "D";
}
然后……
public partial class Form1 : Form
{
xlsLayout xlLayout = new xlsLayout();
xl.SetCell(xlLayout.xlFileColumn, xlLayout.xlHeaderRow, "File Name");
xl.SetCell(xlLayout.xlFieldColumn, xlLayout.xlHeaderRow, "Code field name");
xl.SetCell(xlLayout.xlFreindlyNameColumn, xlLayout.xlHeaderRow, "Freindly name");
xl.SetCell(xlLayout.xlHelpTextColumn, xlLayout.xlHeaderRow, "Inline Help Text");
}