使用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