C# 使用 EnumMemberAttribute 并进行自动字符串转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10418651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 13:46:22  来源:igfitidea点击:

Using EnumMemberAttribute and doing automatic string conversions

c#enums

提问by bryanjonker

I have the following code

我有以下代码

[DataContract]
public enum StatusType
{
    [EnumMember(Value = "A")]
    All,
    [EnumMember(Value = "I")]
    InProcess,
    [EnumMember(Value = "C")]
    Complete,
}

I'd like to do the following:

我想做以下事情:

 var s = "C";
 StatusType status = SerializerHelper.ToEnum<StatusType>(s);   //status is now StatusType.Complete
 string newString = SerializerHelper.ToEnumString<StatusType>(status);   //newString is now "C"

I've done the second part using DataContractSerializer (see code below), but it seems like a lot of work.

我已经使用 DataContractSerializer 完成了第二部分(请参阅下面的代码),但这似乎需要做很多工作。

Am I missing something obvious? Ideas? Thanks.

我错过了一些明显的东西吗?想法?谢谢。

    public static string ToEnumString<T>(T type)
    {
        string s;
        using (var ms = new MemoryStream())
        {
            var ser = new DataContractSerializer(typeof(T));
            ser.WriteObject(ms, type);
            ms.Position = 0;
            var sr = new StreamReader(ms);
            s = sr.ReadToEnd();
        }
        using (var xml = new XmlTextReader(s, XmlNodeType.Element, null))
        {
            xml.MoveToContent();
            xml.Read();
            return xml.Value;
        }
    }

采纳答案by empi

Here is my proposition - it should give you the idea on how to do this (check also Getting attributes of Enum's value):

这是我的提议 - 它应该让您了解如何执行此操作(另请检查Getting attributes of Enum's value):

public static string ToEnumString<T>(T type)
{
    var enumType = typeof (T);
    var name = Enum.GetName(enumType, type);
    var enumMemberAttribute = ((EnumMemberAttribute[])enumType.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true)).Single();
    return enumMemberAttribute.Value;
}

public static T ToEnum<T>(string str)
{
    var enumType = typeof(T);
    foreach (var name in Enum.GetNames(enumType))
    {
        var enumMemberAttribute = ((EnumMemberAttribute[])enumType.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true)).Single();
        if (enumMemberAttribute.Value == str) return (T)Enum.Parse(enumType, name);
    }
    //throw exception or whatever handling you want or
    return default(T);
}

回答by Tim S.

You can use reflection to get the value of the EnumMemberAttribute.

您可以使用反射来获取EnumMemberAttribute.

public static string ToEnumString<T>(T instance)
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("instance", "Must be enum type");
    string enumString = instance.ToString();
    var field = typeof(T).GetField(enumString);
    if (field != null) // instance can be a number that was cast to T, instead of a named value, or could be a combination of flags instead of a single value
    {
        var attr = (EnumMemberAttribute)field.GetCustomAttributes(typeof(EnumMemberAttribute), false).SingleOrDefault();
        if (attr != null) // if there's no EnumMember attr, use the default value
            enumString = attr.Value;
    }
    return enumString;
}

Depending on how your ToEnumworks, you might want to use this sort of approach there as well. Also, the type can be inferred when calling ToEnumString, e.g. SerializerHelper.ToEnumString(status);

根据您的ToEnum工作方式,您可能还想在那里使用这种方法。此外,调用时可以推断类型ToEnumString,例如SerializerHelper.ToEnumString(status);

回答by Simon Ness

If your project references Newtonsoft.Json(what doesn't these days?!), then there is a simple one line solution that doesn't need reflection:

如果您的项目引用了Newtonsoft.Json(现在还有什么?!),那么有一个简单的单行解决方案,不需要反射:

public static string ToEnumString<T>(T value)
{
   return JsonConvert.SerializeObject(value).Replace("\"", "");
}

public static T ToEnum<T>(string value)
{
   return JsonConvert.DeserializeObject<T>($"\"{value}\"");
}

The ToEnumStringmethod will only work if you have the StringEnumConverterregistered in your JsonSerializerSettings(see JavaScriptSerializer - JSON serialization of enum as string), e.g.

ToEnumString方法仅在您已StringEnumConverter注册JsonSerializerSettings(请参阅JavaScriptSerializer - enum as string 的 JSON 序列化)时才有效,例如

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    Converters = { new StringEnumConverter() }
};

Another advantage of this method is that if only some of your enum elements have the member attribute, things still work as expected, e.g.

这种方法的另一个优点是,如果只有一些 enum 元素具有成员属性,事情仍然按预期工作,例如

public enum CarEnum
{
    Ford,
    Volkswagen,
    [EnumMember(Value = "Aston Martin")]
    AstonMartin
}