使用generics方法获取我的枚举属性的List

一开始,我们有这个基本的枚举。

public enum E_Levels { [ValueOfEnum("Low level")] LOW, [ValueOfEnum("Normal level")] NORMAL, [ValueOfEnum("High level")] HIGH } 

我想得到一个List 无论枚举 。 类似Extensions.GetValuesOfEnum() ,它可以返回List其中包含“低级别”,“正常级别”和“高级别”。

StackOF帮助我获得了一个值属性:

 public static class Extensions { public static string ToValueOfEnum(this Enum value) { FieldInfo fieldInfo = value.GetType().GetField(value.ToString()); ValueOfEnum[] attribs = fieldInfo.GetCustomAttributes(typeof(ValueOfEnum), false) as ValueOfEnum[]; return attribs.Length > 0 ? attribs[0].value : null; } } 

无论枚举如何,我都可以调用此方法: E_Levels.LOW.ToValueOfEnum()

此外,StackOF帮助我获得特定枚举的List 。 我在控制器中制作了这个方法:

 private List GetLevels() { List levelsToReturn = new List(); var levels = Enum.GetValues(typeof(E_Levels)).Cast(); foreach(E_Levels l in levels) levelsToReturn.Add(l.ToValueOfEnum()); return levelsToReturn; } 

但是这种方式要求我为每个枚举重写相同的方法。
所以我试着在我的类Extensions中添加这个generics方法:

 public static class Extensions { public static string ToValueOfEnum(this Enum value) {...} public static List GetValuesOf() { List levelsToReturn = new List(); var levels = Enum.GetValues(typeof(T)).Cast(); foreach(T l in levels) levelsToReturn.Add(l.ToValueOfEnum()); return levelsToReturn; } } 

但在我的foreach中, .ToValueOfEnum()是一种未知的方法。

所以我遇到了麻烦,我希望我能找到一种方法,不会一次又一次地为每个枚举重写相同的方法……

让我们试着保持这个更普遍的目的。

我有一个扩展方法 ,可以从枚举值中获取属性。 这将使您可以快速访问属性。

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

使用此function,您可以创建一些查询以获得所需内容。

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

所以你的GetValuesOf()方法(对于这种专业方法恕我直言并不是一个很好的名字)可以像这样写:

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

现在您可以这样调用方法:

 var levelValues = GetValueOf(); // levelValues = { "Low level", "Normal level", "High level" } 

您可以尝试转换(Enum)(object)l ,更改ToValueOfEnum以获取object ,或者只是内联方法:

 public static List GetValuesOf() { List levelsToReturn = new List(); var levels = Enum.GetValues(typeof(T)).Cast(); 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; } 

这是使用铸造方法的单线解决方案:

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

如果你不清楚为什么T不像E_Levels那样被识别为Enum ,那是因为你没有指定T : enum 。 不幸的是,你不能在C#中指定它(即使CLR支持它),所以其他方法,如运行时检查/假设(例如我在这里建议)或后编译代码修改(例如无约束旋律 )要完成。

.Net已经具有相同的属性Description因此您可以使用此属性而不是ValueOfEnum

如何在type和以下示例上进行dynamic和扩展

 [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 ToValues(this Type value) { var result = new List(); var values = ToConcreteValues(value); foreach (dynamic item in values) { Description attribute = GetAttribute(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(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 } 

结果输出:

 Low level Normal level High level