使用 EnumMemberAttribute 进行自动字符串转换
使用 EnumMemberAttribute 进行自动字符串转换
我有以下的代码:
[DataContract] public enum StatusType { [EnumMember(Value = "A")] 全部, [EnumMember(Value = "I")] 进行中, [EnumMember(Value = "C")] 完成, }
我想要做以下的事情:
var s = "C"; StatusType status = SerializerHelper.ToEnum(s); //status 现在是 StatusType.Complete string newString = SerializerHelper.ToEnumString (status); //newString 现在是 "C"
我已经用DataContractSerializer完成了第二部分(见下方代码),不过感觉有点麻烦。
我是否漏掉了一些明显的东西?有什么好的想法吗?谢谢。
public static string ToEnumString(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; } }
使用EnumMemberAttribute和自动字符串转换
问题的出现原因:
在C#中,枚举类型的成员通常以整数形式表示。但是,在某些情况下,我们可能需要将枚举成员的值表示为字符串。为了实现这一目的,我们可以使用EnumMemberAttribute属性来指定每个枚举成员的字符串值。然而,在使用这种方法时,我们可能会遇到一些问题。
解决方法:
为了解决这个问题,我们可以使用扩展方法和C# 7.3的约束来实现自动的字符串转换。上面提供的代码演示了如何定义一个扩展类EnumMemberExtensions,并在其中实现了ToEnumString和ToEnum两个扩展方法。
ToEnumString方法接受一个泛型参数T,该参数必须是Enum类型的子类。它使用反射来获取枚举成员的名称,并通过Enum.GetName方法获取枚举成员的名称。然后,它使用反射来获取EnumMemberAttribute属性,并返回其值。
ToEnum方法接受一个字符串参数str,并返回一个泛型参数T的枚举类型。它使用反射来遍历枚举类型的所有成员,并获取每个成员的EnumMemberAttribute属性。然后,它将传入的字符串与每个成员的属性值进行比较,如果匹配,则返回该成员。
这些扩展方法提供了一种简便的方法来实现枚举成员的自动字符串转换。通过使用EnumMemberAttribute属性,我们可以在需要字符串表示的枚举成员上指定值,并使用这些扩展方法来进行转换。
是否有等效的.NET Core解决方案?
在.NET Core中,我们可以使用相同的方法来实现枚举成员的自动字符串转换。上述提供的代码是通用的,可以在.NET Core中使用。因此,不需要额外的解决方案来实现这个功能。
问题的原因是需要将枚举类型转换为字符串,并且需要自动进行转换。
为了解决这个问题,可以使用EnumMemberAttribute属性和自动字符串转换。
首先,我们可以定义一个ToEnumString方法,该方法接受一个泛型参数T,并返回一个字符串。该方法使用反射获取枚举类型的名称,并获取EnumMemberAttribute属性的值。
其次,我们可以定义一个ToEnum方法,该方法接受一个字符串参数,并返回一个泛型T。该方法使用反射获取枚举类型的名称,并获取EnumMemberAttribute属性的值,然后将值与输入的字符串进行比较,如果匹配,则使用Enum.Parse方法将字符串转换为枚举类型。
最后,我们可以根据需要进行异常处理或返回默认值。
下面是代码示例:
public static string ToEnumString(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 (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); }
使用EnumMemberAttribute属性和自动字符串转换,我们可以方便地将枚举类型转换为字符串,并实现自动转换功能。这样,我们就可以更灵活地处理枚举类型和字符串之间的转换。
问题的原因:
问题的出现是因为在项目中引用了Newtonsoft.Json库。在使用该库进行JSON序列化和反序列化时,枚举类型默认会被转换为整数值。然而,有时候我们希望将枚举类型转换为字符串进行处理。这就需要使用EnumMemberAttribute特性来标注枚举成员的字符串值,并且通过自定义转换方法来实现自动的字符串转换。
解决方法:
解决方法是使用EnumMemberAttribute特性和Newtonsoft.Json库提供的方法来实现自动的字符串转换。
首先,我们可以定义一个ToEnumString方法,该方法接受一个枚举类型的值作为参数,并返回对应的字符串值。具体实现如下:
public static string ToEnumString(T value) { return JsonConvert.SerializeObject(value).Replace("\"", ""); }
然后,我们可以定义一个ToEnum方法,该方法接受一个字符串值作为参数,并返回对应的枚举类型的值。具体实现如下:
public static T ToEnum(string value) { return JsonConvert.DeserializeObject ($"\"{value}\""); }
为了使ToEnumString方法正常工作,我们需要在JsonSerializerSettings中注册StringEnumConverter转换器。具体实现如下:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = { new StringEnumConverter() } };
另外,如果只有枚举的部分成员使用了EnumMemberAttribute特性,该方法仍然可以正常工作。
对于ToEnumString方法,还可以使用JsonConvert提供的另一个重载方法来简化代码,具体实现如下:
return JsonConvert.SerializeObject(value, new StringEnumConverter()).Replace("\"", "");
这样就不需要单独注册转换器了。
通过以上方法,我们可以实现枚举类型和字符串之间的自动转换,方便进行JSON序列化和反序列化的操作。