我有以下代码
[DataContract]
public enum StatusType
{
[EnumMember(Value = "A")]
All,
[EnumMember(Value = "I")]
InProcess,
[EnumMember(Value = "C")]
Complete,
}
我想做以下事情:
var s = "C";
StatusType status = SerializerHelper.ToEnum<StatusType>(s); //status is now StatusType.Complete
string newString = SerializerHelper.ToEnumString<StatusType>(status); //newString is now "C"
我已经使用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;
}
}
答案 0 :(得分:30)
这是我的主张 - 它应该让你知道如何做到这一点(另请查看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);
}
答案 1 :(得分:3)
您可以使用反射来获取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;
}
根据ToEnum
的工作方式,您可能也希望在此处使用此类方法。此外,可以在调用ToEnumString
时推断出类型,例如SerializerHelper.ToEnumString(status);
答案 2 :(得分:1)
使用扩展名和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;
}
}
答案 3 :(得分:1)
此示例说明如何使用 DescriptionAttribute
、EnumMemberAttribute
和属性名称转换枚举:
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
public static class EnumExtensions
{
public static T ToEnumByAttributes<T>(this string value)
where T:Enum
{
var enumType = typeof(T);
foreach (var name in Enum.GetNames(enumType))
{
var field = enumType.GetField(name);
if(field == null) continue;
var enumMemberAttribute = GetEnumMemberAttribute(field);
if (enumMemberAttribute != null && enumMemberAttribute.Value == value)
{
return (T)Enum.Parse(enumType, name);
}
var descriptionAttribute = GetDescriptionAttribute(field);
if (descriptionAttribute != null && descriptionAttribute.Description == value)
{
return (T)Enum.Parse(enumType, name);
}
if (name == value)
{
return (T)Enum.Parse(enumType, name);
}
}
throw new ArgumentOutOfRangeException(nameof(value), value, $"The value could not be mapped to type {enumType.FullName}");
}
public static string ToStringByAttributes(this Enum value)
{
var field = value
.GetType()
.GetField(value.ToString());
if (field == null) return string.Empty;
var enumMemberAttribute = GetEnumMemberAttribute(field);
if (enumMemberAttribute != null)
{
return enumMemberAttribute.Value ?? string.Empty;
}
var descriptionAttribute = GetDescriptionAttribute(field);
if (descriptionAttribute != null)
{
return descriptionAttribute.Description;
}
return value.ToString();
}
private static DescriptionAttribute? GetDescriptionAttribute(FieldInfo field)
{
return field
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.OfType<DescriptionAttribute>()
.SingleOrDefault();
}
private static EnumMemberAttribute? GetEnumMemberAttribute(FieldInfo field)
{
return field
.GetCustomAttributes(typeof(EnumMemberAttribute), false)
.OfType<EnumMemberAttribute>()
.SingleOrDefault();
}
}
NUnit 测试:
[TestFixture]
public sealed class EnumExtensionsTests
{
public enum TestEnum
{
[EnumMember(Value = "A")]
Alpha,
[Description("O")]
Omega
}
[Test]
public void ShouldSerialize_FromEnumAttribute()
{
var result = TestEnum.Alpha.ToStringByAttributes();
Assert.That(result, Is.EqualTo("A"));
}
[Test]
public void ShouldSerialize_FromDescriptionAttribute()
{
var result = TestEnum.Omega.ToStringByAttributes();
Assert.That(result, Is.EqualTo("O"));
}
[Test]
public void ShouldDeserialize_FromEnumAttribute()
{
var result = "A".ToEnumByAttributes<TestEnum>();
Assert.That(result, Is.EqualTo(TestEnum.Alpha));
}
[Test]
public void ShouldDeserialize_FromDescriptionAttribute()
{
var result = "O".ToEnumByAttributes<TestEnum>();
Assert.That(result, Is.EqualTo(TestEnum.Omega));
}
[Test]
public void ShouldDeserialize_FromPropertyName()
{
var result = "Alpha".ToEnumByAttributes<TestEnum>();
Assert.That(result, Is.EqualTo(TestEnum.Alpha));
}
}
答案 4 :(得分:0)
如果您的项目引用了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}\"");
}
仅当您在ToEnumString
中注册了StringEnumConverter
时,JsonSerializerSettings
方法才有效(请参阅.NET - JSON serialization of enum as string)。