首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Key = Enums Name和Value = Enums Value使用最佳技术创建键值对列表

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

Stack Overflow用户
提问于 2013-11-21 10:20:37
回答 3查看 10.6K关注 0票数 3

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

另外,在C#中,如何创建键值对列表,其中键是枚举名称,值是属性EnumName名称。

我希望有两个基于枚举名称的单独列表,以便从属性中检索值或人类可读的名称。

示例:

代码语言:javascript
复制
public enum QATypes
{

    [EnumMember(Value = "Black Box")]
     BlackBox = 10,
    [EnumMember(Value = "Integration Tests")]
     IntegrationTests = 20,
    [EnumMember(Value = "Acceptance Testing")]
     AcceptanceTesting= 30,
...

     }

对于值,第一个列表如下所示:

代码语言:javascript
复制
{{ key:"BlackBox", value:10 }, { key:"IntegrationTests ", value:20 },{ key:"AcceptanceTesting", value:30 },...}

对于枚举成员,第二个列表如下所示:

代码语言:javascript
复制
{{ key:"BlackBox", value:"Black Box"}, { key:"IntegrationTests ", value:"Integration Tests"},{ key:"AcceptanceTesting", value:"Acceptance Testing"},...}
EN

回答 3

Stack Overflow用户

发布于 2013-11-21 17:38:32

您可以使用反射。试试这个(假设所有的枚举成员都有一个EnumMemberAttribute):

代码语言:javascript
复制
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

代码语言:javascript
复制
var valuesJson = JsonConvert.SerializeObject(valuesList);
Console.WriteLine(valuesJson);

输出:

代码语言:javascript
复制
[
    {
        "key": "BlackBox",
        "value": 10
    },
    {
        "key": "IntegrationTests",
        "value": 20
    },
    {
        "key": "AcceptanceTesting",
        "value": 30
    }
]

代码语言:javascript
复制
var nameValuesJson = JsonConvert.SerializeObject(nameValuesList);
Console.WriteLine(nameValuesJson);

以下哪项输出:

代码语言:javascript
复制
[
    {
        "key": "BlackBox",
        "value": "Black Box"
    },
    {
        "key": "IntegrationTests",
        "value": "Integration Tests"
    },
    {
        "key": "AcceptanceTesting",
        "value": "Acceptance Testing"
    }
]

关于返回的订单和异常处理的一些说明

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

代码语言:javascript
复制
[SecuritySafeCritical]
private static void GetCachedValuesAndNames
    (RuntimeType enumType, 
    out ulong[] values, 
    out string[] names, 
    bool getValues, 
    bool getNames)

最终在这个方法上:

代码语言:javascript
复制
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport("QCall", CharSet = CharSet.Unicode)]
private static extern void GetEnumValuesAndNames
    (RuntimeTypeHandle enumType, 
    ObjectHandleOnStack values, 
    ObjectHandleOnStack names, 
    bool getValues, 
    bool getNames);

我提供的代码片段并没有涵盖所有异常,它依赖于原始问题中提供的样本数据。例如,它不检查是否存在EnumMemberAttribute或它的Value属性。但这一点很容易改变,只需花一点力气。

票数 3
EN

Stack Overflow用户

发布于 2013-11-21 18:14:20

当您有值相同但名称不同的枚举成员时,Enum.GetValues是危险的,例如:

代码语言:javascript
复制
enum { A, B = A, C }

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

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

代码语言:javascript
复制
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();
    }
}

这是完全通用的,所以您需要更多的类型才能调用。现在我可以这样做了:

代码语言:javascript
复制
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类成为非静态的,这将帮助您更好地进行类型推断,从而使调用代码更短。应该如下所示:

代码语言:javascript
复制
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);
票数 3
EN

Stack Overflow用户

发布于 2013-11-21 17:10:25

对于第一个问题:

代码语言:javascript
复制
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));
}

关于第二个问题:

代码语言:javascript
复制
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));
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20111231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档