所以我需要从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;
}
}
}