使用Key = Enums Name和Value = Enums值使用最佳技术创建键值对列表

时间:2013-11-21 02:20:37

标签: c# enums

在C#4.0 - 5.0中,如何创建一个键值对列表,其中键是枚举名称的值,值是枚举名称值。

同样在C#中,如何创建一个键值对列表,其中键是枚举名称,值是属性EnumName name。

我想根据枚举的名称设置两个单独的列表,以便从属性中检索值或人类可读的名称。

示例:

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 },...}

,对于enumsmember,第二个列表看起来像这样:

{{ key:"BlackBox", value:"Black Box"}, { key:"IntegrationTests ", value:"Integration Tests"},{ key:"AcceptanceTesting", value:"Acceptance Testing"},...}

3 个答案:

答案 0 :(得分:3)

您可以使用反射。试试这个(假设所有枚举成员都有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"
    }
]

有关退回订单和异常处理的一些评论

依赖GetEnumValuesGetEnumNames返回的项目的顺序似乎而不是是潜在的问题,因为这两种方法都在内部依赖于同一方法:

[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属性。但这可以通过一些努力轻松改变。

答案 1 :(得分:3)

如果枚举成员具有相同的值但名称不同,则

Enum.GetValues会很危险,例如:

enum { A, B = A, C }

您应该使用Enum.GetNames,然后获取相应的值。

我有这个帮助类来处理类似的事情:

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);

您可以在合适的命名空间中创建自己的扩展方法,您无需传递枚举属性类型参数,以便于调用。


此外,您可以使辅助类非静态,这将有助于您更好地使用类型推断,并且从而使调用代码更短。应该是这样的:

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);

答案 2 :(得分:0)

对于第一个问题:

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));
    }
}
相关问题