通过自定义属性获取枚举(通用)

时间:2016-03-21 12:23:23

标签: c# generics enums custom-attributes

有许多示例可以通过自定义属性获取枚举属性,例如此处 Get Enum from Description attribute

public static class EnumEx
{
    public static T GetValueFromDescription<T>(string description)
    {
        var type = typeof(T);
        if(!type.IsEnum) throw new InvalidOperationException();
        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 ArgumentException("Not found.", "description");
        // or return default(T);
    }
}

但问题是您必须对attributeType进行硬编码,即typeof(DescriptionAttribute)) as DescriptionAttribute

如何将此示例转换为通用扩展,以便我不必硬编码CustomAttributeType。

3 个答案:

答案 0 :(得分:5)

这适用于要将值作为字符串进行比较的任何属性:

public static TEnum GetValueFromAttribute<TEnum, TAttribute>
           (string text, Func<TAttribute, string> valueFunc) where TAttribute : Attribute
{ 
   var type = typeof(TEnum);
   if(!type.IsEnum) throw new InvalidOperationException();
   foreach(var field in type.GetFields())
   {
       var attribute = Attribute.GetCustomAttribute(field, typeof(TAttribute)) as TAttribute;
       if(attribute != null)
       {
           if(valueFunc.Invoke(attribute) == text)
               return (TEnum)field.GetValue(null);
       }
       else
       {
           if(field.Name == text)
               return (TEnum)field.GetValue(null);
       }
   }
   throw new ArgumentException("Not found.", "text");
    // or return default(T);
}

然后你会这样打电话:

 var value = GetValueFromAttribute<MyEnum, Description>("desc_text", a => a.Description);

答案 1 :(得分:0)

您可以添加属性实现的接口IDescription

public interface IDescription
{
    string Description { get; }
}

public static class EnumEx
{
    public static T GetValueFromDescription<T, TAttribute>(string description) where TAttribute : Attribute, IDescription
    {
        var type = typeof(T);

        if (!type.IsEnum) throw new InvalidOperationException();

        foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static))
        {
            var attribute = (IDescription)Attribute.GetCustomAttribute(field, typeof(TAttribute));

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

        throw new ArgumentException("Not found.", "description");
        // or return default(T);
    }
}

或等同于完整的基类:

public abstract class BaseDescriptionAttribute : Attribute
{
    public string Description { get; protected set; }
}

public static class EnumEx
{
    public static T GetValueFromDescription<T, TAttribute>(string description) where TAttribute : BaseDescriptionAttribute
    {
        var type = typeof(T);

        if (!type.IsEnum) throw new InvalidOperationException();

        foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static))
        {
            var attribute = (BaseDescriptionAttribute)Attribute.GetCustomAttribute(field, typeof(TAttribute));

答案 2 :(得分:0)

添加新的通用类型

public static T GetValueFromDescription<T, K>(string description)

并在GetCustomerAttribute

中使用它
var attribute = Attribute.GetCustomAttribute(field, typeof(K));