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

Waq*_*med 1 c# generics enums custom-attributes

有很多示例可以通过自定义属性获取Enum,例如此处 从描述属性获取枚举

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

但问题是你必须硬编码attributeType即 typeof(DescriptionAttribute)) as DescriptionAttribute

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

stu*_*rtd 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);
}
Run Code Online (Sandbox Code Playgroud)

然后你会这样打电话:

 var value = GetValueFromAttribute<MyEnum, Description>("desc_text", a => a.Description);
Run Code Online (Sandbox Code Playgroud)