在C# 4.0 - 5.0中,如何创建一个键值对列表,其中键是枚举名称的值,值是枚举名称的值。
另外,在C#中,如何创建键值对列表,其中键是枚举名称,值是属性EnumName名称。
我希望有两个基于枚举名称的单独列表,以便从属性中检索值或人类可读的名称。
示例:
public enum QATypes
{
[EnumMember(Value = "Black Box")]
BlackBox = 10,
[EnumMember(Value = "Integration Tests")]
IntegrationTests = 20,
[EnumMember(Value = "Acceptance Testing")]
AcceptanceTesting= 30,
...
}对于值,第一个列表如下所示:
{{ key:"BlackBox", value:10 }, { key:"IntegrationTests ", value:20 },{ key:"AcceptanceTesting", value:30 },...}对于枚举成员,第二个列表如下所示:
{{ key:"BlackBox", value:"Black Box"}, { key:"IntegrationTests ", value:"Integration Tests"},{ key:"AcceptanceTesting", value:"Acceptance Testing"},...}发布于 2013-11-21 17:38:32
您可以使用反射。试试这个(假设所有的枚举成员都有一个EnumMemberAttribute):
var qatype = typeof(QATypes);
var names = qatype.GetEnumNames();
var values = qatype.GetEnumValues().Cast<int>().ToList();
var nameValues = names.Select(n =>
qatype.GetMember(n)[0]
.CustomAttributes.First()
.NamedArguments[0].TypedValue
.Value)
.ToList();
var valuesList = names.Select((n, index) =>
new { key = n, value = values[index] })
.ToList();
var nameValuesList = names.Select((n, index) =>
new { key = n, value = nameValues[index] })
.ToList();此外,由于您的问题似乎与JSON相关,如果您希望以JSON格式序列化列表,则可以使用Json.NET
var valuesJson = JsonConvert.SerializeObject(valuesList);
Console.WriteLine(valuesJson);输出:
[
{
"key": "BlackBox",
"value": 10
},
{
"key": "IntegrationTests",
"value": 20
},
{
"key": "AcceptanceTesting",
"value": 30
}
]和
var nameValuesJson = JsonConvert.SerializeObject(nameValuesList);
Console.WriteLine(nameValuesJson);以下哪项输出:
[
{
"key": "BlackBox",
"value": "Black Box"
},
{
"key": "IntegrationTests",
"value": "Integration Tests"
},
{
"key": "AcceptanceTesting",
"value": "Acceptance Testing"
}
]关于返回的订单和异常处理的一些说明
依赖于GetEnumValues和GetEnumNames返回的项的顺序似乎不是一个潜在的问题,因为这两个方法在内部依赖于相同的方法:
[SecuritySafeCritical]
private static void GetCachedValuesAndNames
(RuntimeType enumType,
out ulong[] values,
out string[] names,
bool getValues,
bool getNames)最终在这个方法上:
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport("QCall", CharSet = CharSet.Unicode)]
private static extern void GetEnumValuesAndNames
(RuntimeTypeHandle enumType,
ObjectHandleOnStack values,
ObjectHandleOnStack names,
bool getValues,
bool getNames);我提供的代码片段并没有涵盖所有异常,它依赖于原始问题中提供的样本数据。例如,它不检查是否存在EnumMemberAttribute或它的Value属性。但这一点很容易改变,只需花一点力气。
发布于 2013-11-21 18:14:20
当您有值相同但名称不同的枚举成员时,Enum.GetValues是危险的,例如:
enum { A, B = A, C }您应该使用Enum.GetNames,然后获取相应的值。
我有这个helper类来处理类似的事情:
public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
public static IEnumerable<T> GetValues()
{
return (T[])Enum.GetValues(typeof(T));
}
public static IEnumerable<string> GetNames()
{
return Enum.GetNames(typeof(T));
}
public static T Parse(string @enum)
{
return (T)Enum.Parse(typeof(T), @enum);
}
public static S GetAttribute<S>(string @enum) where S : Attribute
{
return (S)typeof(T).GetMember(@enum)[0]
.GetCustomAttributes(typeof(S), false)
.SingleOrDefault();
}
}这是完全通用的,所以您需要更多的类型才能调用。现在我可以这样做了:
var first = Enum<QATypes>.GetNames().ToDictionary(x => x, x => (int)Enum<QATypes>.Parse(x));
var second = first.ToDictionary(x => x.Key, x => Enum<QATypes>.GetAttribute<EnumMemberAttribute>(x.Key).Value);您可以在适当的名称空间中创建自己的扩展方法,在该名称空间中不需要传递枚举属性类型参数,以简化调用。
您还可以使helper类成为非静态的,这将帮助您更好地进行类型推断,从而使调用代码更短。应该如下所示:
var helper = new Enum<QATypes>();
var first = helper.GetNames().ToDictionary(x => x, x => (int)helper.Parse(x));
var second = first.ToDictionary(x => x.Key, x => helper.GetAttribute<EnumMemberAttribute>(x.Key).Value);发布于 2013-11-21 17:10:25
对于第一个问题:
var list = new List<KeyValuePair<string,int>>();
foreach(var e in Enum.GetValues(typeof(QATypes)))
{
list.Add(new KeyValuePair<string,int>(e.ToString(), (int)e));
}关于第二个问题:
var list = new List<KeyValuePair<string,string>>();
foreach(var e in typeof(QATypes).GetFields())
{
var attribute = e.GetCustomAttributes(typeof(EnumMemberAttribute))
.FirstOrDefault() as EnumMemberAttribute;
if(attribute != null)
{
list.Add(new KeyValuePair<string,string>(e.Name, attribute.Value));
}
}https://stackoverflow.com/questions/20111231
复制相似问题