如何获得具有反射的枚举值的所有描述



所以我需要从enum

中得到List<string>

到目前为止我所做的是:

枚举定义

    [Flags]
    public enum ContractorType
    {
        [Description("Recipient")]
        RECIPIENT = 1,
        [Description("Deliver")]
        DELIVER = 2,
        [Description("Recipient / Deliver")]
        RECIPIENT_DELIVER = 4
    }

HelperClass with method to do what I need

public static class EnumUtils
{
    public static IEnumerable<string> GetDescrptions(Type enumerator)
    {
        FieldInfo[] fi = enumerator.GetFields();
        List<DescriptionAttribute> attributes = new List<DescriptionAttribute>();
        foreach (var i in fi)
        {
            try
            {
                yield return attributes.Add(((DescriptionAttribute[])i.GetCustomAttributes(
                    typeof(DescriptionAttribute),
                    false))[0]);
            }
            catch { }
        }
        return new List<string>{"empty"};
    }
}

现在在我yield值的那一行,我得到了NullReferenceException。我错过什么了吗?语法看起来不错,但也许我忽略了什么?

编辑:

我使用的是。net Framework 4.0

对于获取枚举类型T的每个值的描述列表,这个泛型静态方法工作得很好:

public static IEnumerable<string> GetDescriptions<T>()
{
    var attributes = typeof(T).GetMembers()
        .SelectMany(member => member.GetCustomAttributes(typeof (DescriptionAttribute), true).Cast<DescriptionAttribute>())
        .ToList();
    return attributes.Select(x => x.Description);
}

我创建了这些扩展方法

public static class EnumExtender
{
    public static string GetDescription(this Enum enumValue)
    {
        string output = null;
        Type type = enumValue.GetType();
        FieldInfo fi = type.GetField(enumValue.ToString());
        var attrs = fi.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
        if (attrs.Length > 0) output = attrs[0].Description;
        return output;
    }
    public static IDictionary<T, string> GetEnumValuesWithDescription<T>(this Type type) where T : struct, IConvertible
    {
        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be an enumerated type");
        }
        return type.GetEnumValues()
                .OfType<T>()
                .ToDictionary(
                    key => key,
                    val => (val as Enum).GetDescription()
                );
    }
}
使用

var stuff = typeof(TestEnum).GetEnumValuesWithDescription<TestEnum>();

将返回一个Dictionary<TestEnum, string>,其中value作为键,description作为值。如果你只想要一个列表,你可以把.ToDictionary改成

.Select(o => (o as Enum).GetDescription())
.ToList()

这里是一个小的可重用解决方案。这是一个抽象类,它将从类型T中提取类型K的所有属性。

abstract class AbstractAttributes<T, K>
{
    protected List<K> Attributes = new List<K>();
    public AbstractAttributes()
    {
        foreach (var member in typeof(T).GetMembers())
        {
            foreach (K attribute in member.GetCustomAttributes(typeof(K), true)) 
                Attributes.Add(attribute);                
        }
    }
}

如果我们现在只想提取DescriptionAttribute类型的属性,我们将使用下面的类:

class DescriptionAttributes<T> : AbstractAttributes<T, DescriptionAttribute>
{
    public List<string> Descriptions { get; set; }
    public DescriptionAttributes()
    {
        Descriptions = Attributes.Select(x => x.Description).ToList();
    }
}

该类将只从T类型中提取DescriptionAttribute类型的属性。但是要在您的上下文中实际使用这个类,您只需要执行以下操作:

new DescriptionAttributes<ContractorType>().Descriptions.ForEach(x => Console.WriteLine(x));

这行代码将写出您在类型为DescriptionAttribute的属性中用作参数的所有描述。如果需要提取一些其他属性,只需创建一个从AbstractAttributes<T, K>类派生的新类,并用适当的属性关闭其类型K

您需要在每个字段上找到DescriptionAttribute,如果它存在,然后检索Description属性,例如

return enumType.GetFields()
                .Select(f => (DescriptionAttribute)f.GetCustomAttribute(typeof(DescriptionAttribute)))
                .Where(a => a != null)
                .Select(a => a.Description)

如果你可以在一个字段中有多个描述,你可以这样做:

FieldInfo[] fields = enumType.GetFields();
foreach(FieldInfo field in fields)
{
    var descriptionAttributes = field.GetCustomAttributes(false).OfType<DescriptionAttribute>();
    foreach(var descAttr in descriptionAttributes)
    {
        yield return descAttr.Description;
    }
}

我认为这可以解决你的问题。如果没有实现,您可以返回null或异常。这取决于你需要什么。

public DescriptionAttribute GetDescription(ContractorType contractorType)
{
     MemberInfo memberInfo = typeof(ContractorType).GetMember(contractorType.ToString())
                                          .FirstOrDefault();
     if (memberInfo != null)
    {
         DescriptionAttribute attribute = (DescriptionAttribute) 
                 memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false)
                           .FirstOrDefault();
         return attribute;
    }
    //return null;
    //or
    throw new NotImplementedException("There is no description for this enum");
}

你可以这样使用:

DescriptionAttribute attribute = GetDescription(ContractorType.RECIPIENT);
对不起,我没有读你的问题。下面是一些可以用来获取所有描述字符串的代码:
 public IEnumerable<string> GetAllDescriptionInText()
 {
     List<string> descList = new List<string>();
     foreach (DescriptionAttribute desc in Enum.GetValues(typeof(DescriptionAttribute)))
     {
         descList.Add(GetDescription(desc).Value);
     }
     return descList;
 }

你可以试试这个

public string ContractorTypeDescription(Enum ContractorType)
{
    FieldInfo fi = ContractorType.GetType().GetField(ContractorType.ToString());
    var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
    if (attributes.Length > 0)
    {
        return attributes[0].Description;
    }
    else
    {
        return ContractorType.ToString();
    }
}

这是字典而不是列表
但这是我用的

using System.ComponentModel;
using System.Reflection;
using MyExtensions;
namespace MyExtensions
{
    public static class Extension
    {
        public static string GetDescriptionName(this Enum value)
        {
            Type type = value.GetType();
            string name = Enum.GetName(type, value);
            if (name == null)
                return null;
            else
            {
                FieldInfo field = type.GetField(name);
                if (field == null)
                    return name;
                else
                {
                    DescriptionAttribute attr =
                            Attribute.GetCustomAttribute(field,
                                typeof(DescriptionAttribute)) as DescriptionAttribute;
                    if (attr == null)
                        return name;
                    else
                        return attr.Description;
                }
            }
        }
    }
}
namespace EnumDescription
{
    class Program
    {
        public enum enumDateCond : byte 
        {
            [Description("Empty")]
            Null = 0,
            [Description("Not Empty")]
            NotNull = 1,
            EQ = 2, 
            LT = 3, 
            LE = 4, 
            GE = 14, 
            GT = 15 
        };
        static void Main(string[] args)
        {
            enumDateCond x = enumDateCond.Null;
            string description = x.GetDescriptionName();
            foreach (enumDateCond enm in Enum.GetValues(typeof(enumDateCond)))
            {
                description = enm.GetDescriptionName();
                Console.WriteLine(description);
            }
            Console.WriteLine("Dictionary");
            Dictionary<enumDateCond, string> DLenumDateCond = EnumToDictionary<enumDateCond>();
            foreach(enumDateCond key in DLenumDateCond.Keys)
            {
                Console.WriteLine(key.ToString() + " " + DLenumDateCond[key]);
            }
        }
        public static Dictionary<T, string> EnumToDictionary<T>()
            where T : struct
        {
            Type enumType = typeof(T);
            // Can't use generic type constraints on value types,
            // so have to do check like this
            if (enumType.BaseType != typeof(Enum))
                throw new ArgumentException("T must be of type System.Enum");
            Dictionary<T, string> enumDL = new Dictionary<T, string>();
            foreach (T enm in Enum.GetValues(enumType))
            {
                string name = Enum.GetName(enumType, enm);
                if (name != null)
                {
                    FieldInfo field = enumType.GetField(name);
                    if (field != null)
                    {
                        DescriptionAttribute attr =
                                Attribute.GetCustomAttribute(field,
                                    typeof(DescriptionAttribute)) as DescriptionAttribute;
                        if (attr != null)
                            name = attr.Description;
                    }
                }
                enumDL.Add(enm, name);
            }
            return enumDL;
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新