开发者

Key value pair as enum

Can I have an enum which acts as a key value 开发者_开发知识库pair.

public enum infringementCategory
{ 
    Infringement,
    OFN
}

If I select Infringement I should get "INF0001" and if I select OFN I should get "INF0002"

Is it possible?


You can use decorators in order to associate string representation with your enum values. Check this question: Enum ToString with user friendly strings

It will look like:

public enum infringementCategory
{ 
    [Description("INF0001")]
    Infringement,
    [Description("INF0002")]
    OFN
}

Looks more neat than using Dictionary and needs less maintain.


How about these extensions:

public static class EnumExtension
{
    /// <summary>
    /// Gets the string of an DescriptionAttribute of an Enum.
    /// </summary>
    /// <param name="value">The Enum value for which the description is needed.</param>
    /// <returns>If a DescriptionAttribute is set it return the content of it.
    /// Otherwise just the raw name as string.</returns>
    public static string Description(this Enum value)
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }

        string description = value.ToString();
        FieldInfo fieldInfo = value.GetType().GetField(description);
        DescriptionAttribute[] attributes =
           (DescriptionAttribute[])
         fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if (attributes != null && attributes.Length > 0)
        {
            description = attributes[0].Description;
        }

        return description;
    }

    /// <summary>
    /// Creates an List with all keys and values of a given Enum class
    /// </summary>
    /// <typeparam name="T">Must be derived from class Enum!</typeparam>
    /// <returns>A list of KeyValuePair&lt;Enum, string&gt; with all available
    /// names and values of the given Enum.</returns>
    public static IList<KeyValuePair<Enum, string>> ToList<T>() where T : struct
    {
        var type = typeof(T);

        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be an enum");
        }

        return (IList<KeyValuePair<Enum, string>>)
                Enum.GetValues(type)
                    .OfType<Enum>()
                    .Select(e => new KeyValuePair<Enum, string>(e, e.Description()))
                    .ToArray();
    }

    public static T GetValueFromDescription<T>(string description) where T : struct
    {
        var type = typeof(T);

        if(!type.IsEnum)
        {
            throw new ArgumentException("T must be an enum");
        }

        foreach(var field in type.GetFields())
        {
            var attribute = Attribute.GetCustomAttribute(field,
                typeof(DescriptionAttribute)) as DescriptionAttribute;

            if(attribute != null)
            {
                if(attribute.Description == description)
                {
                    return (T)field.GetValue(null);
                }
            }
            else
            {
                if(field.Name == description)
                {
                    return (T)field.GetValue(null);
                }
            }
        }

        throw new ArgumentOutOfRangeException("description");
        // or return default(T);
    }
}

With this in place you can built up your enum like this:

public enum Foo
{
    [Description("Foo - Something")]
    Something,
    [Description("Foo - Anything")]
    Anything,
}

And get your list like this:

var list = EnumExtension.ToList<Foo>();


You could store the titles (INF0001)... in a Dictionary<infringementCategory, string>


See:

public enum InfringementCategory
{
    [EnumNamedConstant(Description = "INF0001")]
    Infringement,

    [EnumNamedConstant(Description = "INF0002")]
    OFN
}

public class Test{
    public void Test()
    {
        String result = InfringementCategory.Infringement.GetDescription();
    }
}

And here the extension methods...

#region [ EnumNamedConstantAttribute ]
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EnumNamedConstantAttribute : Attribute
{
    public string Description { get; set; }
    public string Value { get; set; }
}
#endregion


#region EnumUtilities
public static class EnumUtilities
{
    #region [ + Extension Methods ]

    #region [ GetDescription ]

    public static string GetDescription(this Enum constant)
    {
        return EnumUtilities.GetEnumNamedConstantAttribute(constant).Description;
    }
    #endregion

    #region [ GetStringValue ]

    public static string GetStringValue(this Enum constant)
    {
        return GetEnumNamedConstantValue(constant);
    }
    #endregion

    #endregion

    #region [ + Static Methods ]

    #region [ GetEnumerable ]

    public static IEnumerable<EnumNamedConstantAttribute> GetEnumerable<T>()
    {
        T instancia = Activator.CreateInstance<T>();

        FieldInfo[] objInfos = instancia.GetType().GetFields(BindingFlags.Public | BindingFlags.Static);
        foreach (FieldInfo objFileInfo in objInfos)
        {
            Enum constant = (Enum)objFileInfo.GetValue(objFileInfo);
            if (objFileInfo.GetCustomAttributes(typeof(EnumNamedConstantAttribute), false).Length != 0)
            {
                yield return new EnumNamedConstantAttribute()
                {
                    Description = EnumUtilities.GetEnumNamedConstantAttribute(constant).Description,
                    Value = GetEnumNamedConstantValue(constant)
                };
            }
        }
    }
    #endregion

    #endregion

    #region [ + Privates ]

    #region [ GetEnumNamedConstantAttribute ]
    private static EnumNamedConstantAttribute GetEnumNamedConstantAttribute(Enum constant)
    {
        FieldInfo[] objInfos = constant.GetType().GetFields(BindingFlags.Public | BindingFlags.Static);
        foreach (FieldInfo objFileInfo in objInfos)
        {
            Enum constantItem = (Enum)objFileInfo.GetValue(objFileInfo);
            if (constantItem.GetHashCode().Equals(constant.GetHashCode()))
            {
                object[] attributes = objFileInfo.GetCustomAttributes(typeof(EnumNamedConstantAttribute), false);

                if (attributes.Length > 0)
                    return (EnumNamedConstantAttribute)attributes[0];
            }
        }
        return null;
    }
    #endregion

    #region [ GetEnumNamedConstantValue ]
    private static string GetEnumNamedConstantValue(Enum constant)
    {
        string sValue = (constant.GetHashCode()).ToString();
        EnumNamedConstantAttribute objRet = EnumUtilities.GetEnumNamedConstantAttribute(constant);
        if (objRet != null)
        {
            String sAux = objRet.Value;
            if (!String.IsNullOrEmpty(sAux))
                sValue = objRet.Value;
        }
        return sValue;
    }
    #endregion

    #endregion
}
#endregion


Update:
Thanks to Oliver for pointing out System.Component.DescriptionAttribute. Here's how to do it:

public enum infringementCategory
{
    [Description("INF0001")]
    Infringement,
    [Description("INF0002")]
    OFN
}

public static class DescriptionExtensions
{
    public static string GetDescriptionValue(this Enum value)
    {
        // Get the type
        Type type = value.GetType();

        // Get fieldinfo for this type
        FieldInfo fieldInfo = type.GetField(value.ToString());

        // Get the stringvalue attributes
        DescriptionAttribute[] attribs = fieldInfo.GetCustomAttributes(
            typeof(DescriptionAttribute), false) as DescriptionAttribute[];

        // Return the first if there was a match.
        return attribs.Length > 0 ? attribs[0].Description : null;
    }
}

public class Program
{
    static void Main(string[] args)
    {
        infringementCategory category = infringementCategory.OFN;
        string description = category.GetDescriptionValue();
    }
}


You have a number of choices:

  1. A Dictionary as vc74 suggested. This is efficient and decouples your enum from the property.

  2. A switch statement

  3. If the only thing you want to associate with each is an integer you can use:

     public enum InfringementCategory
     { 
         Infringement = 1,
         OFN = 2
     }
    

    and then put (int)myEnum into String.Format to turn it into a string of the form you want.

  4. An Attribute

    public enum InfringementCategory
    { 
        [InfID("INF0001")]Infringement,
        [InfID("INF0002")]OFN
    }
    

    For improved performance you can use reflection once to populate dictionary.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜