我有以下列举:

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

其他回答

在你的问题中,你从未说过你实际上需要枚举的数值。

如果你不这样做,只是需要一个string类型的枚举(这不是一个整型,所以不能是enum的基)这里有一个方法:

    static class AuthenticationMethod
    {
        public static readonly string
            FORMS = "Forms",
            WINDOWSAUTHENTICATION = "WindowsAuthentication";
    }

您可以使用与enum相同的语法来引用它

if (bla == AuthenticationMethod.FORMS)

它将比使用数值(比较字符串而不是数字)稍微慢一些,但从好的方面来看,它不使用反射(慢)来访问字符串。

如果我理解正确,你可以简单地使用.ToString()从值中检索enum的名称(假设它已经被转换为enum); 如果你有裸整型(比如从数据库或其他地方),你可以先将它强制转换为枚举。 下面的两个方法都将获得枚举名称。

AuthenticationMethod myCurrentSetting = AuthenticationMethod.FORMS;
Console.WriteLine(myCurrentSetting); // Prints: FORMS
string name = Enum.GetNames(typeof(AuthenticationMethod))[(int)myCurrentSetting-1];
Console.WriteLine(name); // Prints: FORMS

但是请记住,第二种技术假设您使用的是int型,并且您的索引基于1(而不是基于0)。相比之下,GetNames函数也相当繁重,每次调用它都要生成一个完整的数组。 正如您在第一种技术中看到的,. tostring()实际上是隐式调用的。 这两个问题都已经在答案中提到了,当然,我只是想澄清它们之间的区别。

试试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(); }

我的变体

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)。

如果你来这里是为了实现一个简单的“Enum”,但其值是字符串而不是int,这里有一个最简单的解决方案:

    public sealed class MetricValueList
    {
        public static readonly string Brand = "A4082457-D467-E111-98DC-0026B9010912";
        public static readonly string Name = "B5B5E167-D467-E111-98DC-0026B9010912";
    }

实现:

var someStringVariable = MetricValueList.Brand;