Get a List of my enum attributes with a generic method

前端 未结 3 846
面向向阳花
面向向阳花 2020-12-10 07:10

At start, we have this basic enum.

public enum E_Levels {

    [ValueOfEnum(\"Low level\")]
    LOW,

    [ValueOfEnum(\"Normal level\")]
    NORMAL,

    [V         


        
相关标签:
3条回答
  • 2020-12-10 07:52

    You might try casting (Enum)(object)l, changing ToValueOfEnum to take an object, or just inline the method:

    public static List<string> GetValuesOf<T>()
    {
    
        List<string> levelsToReturn = new List<string>();
        var levels = Enum.GetValues(typeof(T)).Cast<T>();
        foreach (T value in levels)
        {
            FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
            ValueOfEnum[] attribs = fieldInfo.GetCustomAttributes(typeof(ValueOfEnum), false) as ValueOfEnum[];
            levelsToReturn.Add(attribs.Length > 0 ? attribs[0].value : null);
        }
    
        return levelsToReturn;
    }
    

    Here's a one-line solution using the casting approach:

    return new List<string>(Enum.GetValues(typeof(T)).Cast<Enum>().Select(x => x.ToValueOfEnum()));
    

    In case you weren't clear on why T wasn't recognized as an Enum like E_Levels is, that's because you didn't specify that T : enum. Unfortunately, you can't specify that in C# (even though the CLR supports it), so other approaches like runtime checking/assuming (such as what I'm suggesting here) or post-compile code modifications (e.g. unconstrained-melody) have to be done.

    0 讨论(0)
  • 2020-12-10 07:59

    Let's try to keep this more general purpose.

    I have an extension method that could grab attributes off of enum values. This would give you quick access to the attributes.

    public static class EnumExtensions
    {
        public static TAttribute GetAttribute<TAttribute>(this Enum value)
            where TAttribute : Attribute
        {
            var type = value.GetType();
            var name = Enum.GetName(type, value);
            return type.GetField(name)
                .GetCustomAttributes(false)
                .OfType<TAttribute>()
                .SingleOrDefault();
        }
    }
    

    Using this, you could create some queries to get what you want.

    var valuesOfLevels =
        Enum.GetValues(typeof(E_Levels)).Cast<E_Levels>()
            .Select(level => level.GetAttribute<ValueOfEnumAttribute>().Value);
    

    So your GetValuesOf() method (which is not a great name for such a specialty method IMHO) can be written like this:

    public static List<string> GetValuesOf<TEnum>()
        where TEnum : struct // can't constrain to enums so closest thing
    {
        return Enum.GetValues(typeof(TEnum)).Cast<Enum>()
                   .Select(val => val.GetAttribute<ValueOfEnumAttribute>().Value)
                   .ToList();
    }
    

    Now you may call the method like so:

    var levelValues = GetValueOf<E_Levels>();
    // levelValues = { "Low level", "Normal level", "High level" }
    
    0 讨论(0)
  • 2020-12-10 08:04

    .Net already has the same attribute Description so you can use this one instead ValueOfEnum.

    What about dynamic and extension on type and following example

    [TestFixture]
    public sealed class ForTest
    {
        [Test]
        public void Test()
        {
            var values = typeof(Levels).ToValues();
            values.ForEach(Console.WriteLine);
        }
    }
    
    public static class TypeExtensions
    {
        public static List<string> ToValues(this Type value)
        {
            var result = new List<string>();
            var values = ToConcreteValues(value);
            foreach (dynamic item in values)
            {
                Description attribute = GetAttribute<Description>(item);
                result.Add(attribute.Description);
            }
            return result;
        }
    
        private static dynamic ToConcreteValues(Type enumType)
        {
            Array values = Enum.GetValues(enumType);
            Type list = typeof (List<>);
            Type resultType = list.MakeGenericType(enumType);
            dynamic result = Activator.CreateInstance(resultType);
            foreach (object value in values)
            {
                dynamic concreteValue = Enum.Parse(enumType, value.ToString());
                result.Add(concreteValue);
            }
            return result;
        }
    
        private static TAttribute GetAttribute<TAttribute>(dynamic value)
            where TAttribute : Attribute
        {
            Type type = value.GetType();
            FieldInfo fieldInfo = type.GetField(Enum.GetName(type, value));
            return (TAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof (TAttribute));
        }
    }
    
    public enum Levels
    {
        [Description("Low level")]LOW,
        [Description("Normal level")] NORMAL,
        [Description("High level")] HIGH
    }
    

    result output:

    Low level
    Normal level
    High level
    
    0 讨论(0)
提交回复
热议问题