我有以下列举:
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);
好的,现在所有这些工作就像一个魅力,但我发现它有很多工作。我想知道有没有更好的解决办法。
我还尝试了一些字典和静态属性,但这也不是更好。
我支持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");
}
试试type-safe-enum模式。
public sealed class AuthenticationMethod {
private readonly String name;
private readonly int value;
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){
this.name = name;
this.value = value;
}
public override String ToString(){
return name;
}
}
更新
显式(或隐式)类型转换可以通过
adding static field with mapping
private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
n.b. In order that the initialisation of the the "enum member" fields doesn't throw a NullReferenceException when calling the instance constructor, be sure to put the Dictionary field before the "enum member" fields in your class. This is because static field initialisers are called in declaration order, and before the static constructor, creating the weird and necessary but confusing situation that the instance constructor can be called before all static fields have been initialised, and before the static constructor is called.
filling this mapping in instance constructor
instance[name] = this;
and adding user-defined type conversion operator
public static explicit operator AuthenticationMethod(string str)
{
AuthenticationMethod result;
if (instance.TryGetValue(str, out result))
return result;
else
throw new InvalidCastException();
}
可以使用ToString()引用名称而不是值
Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());
文档在这里:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
...如果你在Pascal情况下命名你的枚举(如ThisIsMyEnumValue = 1等),那么你可以使用一个非常简单的正则表达式来打印友好的形式:
static string ToFriendlyCase(this string EnumString)
{
return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}
可以很容易地从任何字符串调用:
Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());
输出:
把我疯狂的帕斯卡格句转换成友好格句
这节省了在房子周围运行创建自定义属性并将它们附加到枚举或使用查找表将枚举值与友好字符串结合,最好的是它是自我管理的,可以用于任何Pascal Case字符串,这是无限可重用的。当然,它不允许您使用与解决方案提供的枚举不同的友好名称。
不过,我确实喜欢你针对更复杂场景的原始解决方案。你可以把你的解决方案更进一步,让你的GetStringValue成为你的枚举的扩展方法,然后你就不需要像StringEnum.GetStringValue…
public static string GetStringValue(this AuthenticationMethod value)
{
string output = null;
Type type = value.GetType();
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;
}
然后你可以直接从你的枚举实例中访问它:
Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());