使用EnumMemberAttribute并执行自动字符串转换

bry*_*ker 20 c# enums

我有以下代码

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

我想做以下事情:

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

我已经使用DataContractSerializer完成了第二部分(参见下面的代码),但它似乎做了很多工作.

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

    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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

emp*_*mpi 32

这是我的主张 - 它应该为您提供如何执行此操作的想法(另请参阅获取Enum值的属性):

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);
}
Run Code Online (Sandbox Code Playgroud)


Sim*_*ess 11

如果您的项目引用了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}\"");
}
Run Code Online (Sandbox Code Playgroud)

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

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    Converters = { new StringEnumConverter() }
};
Run Code Online (Sandbox Code Playgroud)

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

public enum CarEnum
{
    Ford,
    Volkswagen,
    [EnumMember(Value = "Aston Martin")]
    AstonMartin
}
Run Code Online (Sandbox Code Playgroud)

  • `string JsonConvert.SerializeObject(object? value, params JsonConvert[] converters)` 存在重载。因此 `ToEnumString` 可以更改为: `return JsonConvert.SerializeObject(value, new StringEnumConverter()).Replace("\"", "");` 这样就不需要单独注册转换器了。 (2认同)

Get*_*toX 9

使用扩展和 C# 7.3 约束

    public static class EnumMemberExtensions
    {
        public static string ToEnumString<T>(this T type)
            where T : Enum
        {
            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>(this string str)
            where T : Enum
        {
            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;
        }
    }
Run Code Online (Sandbox Code Playgroud)