我有以下列举:
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);
好的,现在所有这些工作就像一个魅力,但我发现它有很多工作。我想知道有没有更好的解决办法。
我还尝试了一些字典和静态属性,但这也不是更好。
我发现的Enums国际化或从各自的资源文件获取Enums文本的方法是通过继承DescriptionAttribute类创建一个属性类
public class EnumResourceAttribute : DescriptionAttribute
{
public Type ResourceType { get; private set; }
public string ResourceName { get; private set; }
public int SortOrder { get; private set; }
public EnumResourceAttribute(Type ResourceType,
string ResourceName,
int SortOrder)
{
this.ResourceType = ResourceType;
this.ResourceName = ResourceName;
this.SortOrder = SortOrder;
}
}
创建另一个Static类,为GetString和GetString提供扩展方法。
public static class EnumHelper
{
public static string GetString(this Enum value)
{
EnumResourceAttribute ea =
(EnumResourceAttribute)value.GetType().GetField(value.ToString())
.GetCustomAttributes(typeof(EnumResourceAttribute), false)
.FirstOrDefault();
if (ea != null)
{
PropertyInfo pi = ea.ResourceType
.GetProperty(CommonConstants.ResourceManager);
if (pi != null)
{
ResourceManager rm = (ResourceManager)pi
.GetValue(null, null);
return rm.GetString(ea.ResourceName);
}
}
return string.Empty;
}
public static IList GetStrings(this Type enumType)
{
List<string> stringList = new List<string>();
FieldInfo[] fiArray = enumType.GetFields();
foreach (FieldInfo fi in fiArray)
{
EnumResourceAttribute ea =
(EnumResourceAttribute)fi
.GetCustomAttributes(typeof(EnumResourceAttribute), false)
.FirstOrDefault();
if (ea != null)
{
PropertyInfo pi = ea.ResourceType
.GetProperty(CommonConstants.ResourceManager);
if (pi != null)
{
ResourceManager rm = (ResourceManager)pi
.GetValue(null, null);
stringList.Add(rm.GetString(ea.ResourceName));
}
}
}
return stringList.ToList();
}
}
在Enum的元素上,你可以这样写:
public enum Priority
{
[EnumResourceAttribute(typeof(Resources.AdviceModule), Resources.ResourceNames.AdviceCreateAdviceExternaPriorityMemberHigh, 1)]
High,
[EnumResourceAttribute(typeof(Resources.AdviceModule), Resources.ResourceNames.AdviceCreateAdviceExternaPriorityMemberRoutine, 2)]
Routine
}
Where Resources.ResourceNames.AdviceCreateAdviceExternaPriorityMemberHigh &
resources . resourcename . advicecreateadviceexternaprioritymemberroutine是资源文件中的常量,或者你可以说字符串,其值可以在不同的文化中可用。
如果你在MVC架构中实现你的web应用程序,那么创建一个属性
private IList result;
public IList Result
{
get
{
result = typeof(Priority).GetStrings();
return result;
}
}
在你的.cshtml文件中,你可以像这样将枚举绑定到你的下拉列表:
@Html.DropDownListFor(model => Model.vwClinicalInfo.Priority, new SelectList(Model.Result))
谢谢
Ratnesh
我的变体
public struct Colors
{
private String current;
private static string red = "#ff0000";
private static string green = "#00ff00";
private static string blue = "#0000ff";
private static IList<String> possibleColors;
public static Colors Red { get { return (Colors) red; } }
public static Colors Green { get { return (Colors) green; } }
public static Colors Blue { get { return (Colors) blue; } }
static Colors()
{
possibleColors = new List<string>() {red, green, blue};
}
public static explicit operator String(Colors value)
{
return value.current;
}
public static explicit operator Colors(String value)
{
if (!possibleColors.Contains(value))
{
throw new InvalidCastException();
}
Colors color = new Colors();
color.current = value;
return color;
}
public static bool operator ==(Colors left, Colors right)
{
return left.current == right.current;
}
public static bool operator !=(Colors left, Colors right)
{
return left.current != right.current;
}
public bool Equals(Colors other)
{
return Equals(other.current, current);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(Colors)) return false;
return Equals((Colors)obj);
}
public override int GetHashCode()
{
return (current != null ? current.GetHashCode() : 0);
}
public override string ToString()
{
return current;
}
}
代码看起来有点丑,但是这个结构体的用法很有代表性。
Colors color1 = Colors.Red;
Console.WriteLine(color1); // #ff0000
Colors color2 = (Colors) "#00ff00";
Console.WriteLine(color2); // #00ff00
// Colors color3 = "#0000ff"; // Compilation error
// String color4 = Colors.Red; // Compilation error
Colors color5 = (Colors)"#ff0000";
Console.WriteLine(color1 == color5); // True
Colors color6 = (Colors)"#00ff00";
Console.WriteLine(color1 == color6); // False
此外,我认为,如果需要大量这样的枚举,可能会使用代码生成(例如T4)。
我使用系统中的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()。
选项1:
public sealed class FormsAuth
{
public override string ToString{return "Forms Authtentication";}
}
public sealed class WindowsAuth
{
public override string ToString{return "Windows Authtentication";}
}
public sealed class SsoAuth
{
public override string ToString{return "SSO";}
}
然后
object auth = new SsoAuth(); //or whatever
//...
//...
// blablabla
DoSomethingWithTheAuth(auth.ToString());
选项2:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
public class MyClass
{
private Dictionary<AuthenticationMethod, String> map = new Dictionary<AuthenticationMethod, String>();
public MyClass()
{
map.Add(AuthenticationMethod.FORMS,"Forms Authentication");
map.Add(AuthenticationMethod.WINDOWSAUTHENTICATION ,"Windows Authentication");
map.Add(AuthenticationMethod.SINGLESIGNON ,"SSo Authentication");
}
}
我使用了上述几个建议的组合,并结合了一些缓存。现在,我从网上找到的一些代码中得到了这个想法,但我既不记得是从哪里得到的,也不记得是怎么找到的。所以如果有人发现了一些相似的东西,请在归因处发表评论。
无论如何,使用涉及到类型转换器,所以如果你绑定到UI,它'只是工作'。您可以使用Jakub的模式进行扩展,通过从类型转换器初始化到静态方法来实现快速代码查找。
基本使用量是这样的
[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
自定义枚举类型转换器的代码如下:
public class CustomEnumTypeConverter<T> : EnumConverter
where T : struct
{
private static readonly Dictionary<T,string> s_toString =
new Dictionary<T, string>();
private static readonly Dictionary<string, T> s_toValue =
new Dictionary<string, T>();
private static bool s_isInitialized;
static CustomEnumTypeConverter()
{
System.Diagnostics.Debug.Assert(typeof(T).IsEnum,
"The custom enum class must be used with an enum type.");
}
public CustomEnumTypeConverter() : base(typeof(T))
{
if (!s_isInitialized)
{
Initialize();
s_isInitialized = true;
}
}
protected void Initialize()
{
foreach (T item in Enum.GetValues(typeof(T)))
{
string description = GetDescription(item);
s_toString[item] = description;
s_toValue[description] = item;
}
}
private static string GetDescription(T optionValue)
{
var optionDescription = optionValue.ToString();
var optionInfo = typeof(T).GetField(optionDescription);
if (Attribute.IsDefined(optionInfo, typeof(DescriptionAttribute)))
{
var attribute =
(DescriptionAttribute)Attribute.
GetCustomAttribute(optionInfo, typeof(DescriptionAttribute));
return attribute.Description;
}
return optionDescription;
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value, Type destinationType)
{
var optionValue = (T)value;
if (destinationType == typeof(string) &&
s_toString.ContainsKey(optionValue))
{
return s_toString[optionValue];
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
var stringValue = value as string;
if (!string.IsNullOrEmpty(stringValue) && s_toValue.ContainsKey(stringValue))
{
return s_toValue[stringValue];
}
return base.ConvertFrom(context, culture, value);
}
}
}