我在Enums上使用DescriptionAttribute
来提供包含空格的描述。我创建了一些扩展方法,这些方法将返回枚举的字符串描述和/或从字符串描述返回枚举值。
现在,我希望我的WebAPI使用这些扩展方法来处理Enum类型转换,而不是默认的TypeConverter,以便我可以传递类似"Car Wash"
的值并将其映射到Enum。
是否可以将默认字符串覆盖为Enum TypeConverter?
环境 .NetCore 2.x
更新-我当前的代码
当Controller将对象序列化为JSON以发送到客户端时,我当前的代码非常有用。给定下面的Enum
,枚举值0将导致客户端获得字符串“ Mental Health”-完美。但是,现在客户端将“心理健康”发送回服务器时,我需要将其转换回AgencyTpes.MentalHealth
。现在,绑定引擎会引发错误。
//Example Enum
public enum AgencyTypes {
[Description("Mental Health")]
MentalHealth,
Corrections,
[Description("Drug & Alcohol")]
DrugAndAlcohol,
Probation
}
与DescriptionAttribute
一起使用的我的Enum扩展名
public static class EnumExtensions
{
public static string ToDisplayString(this Enum values)
{
var attribute = value.GetType().GetMember(value.ToString())
.FirstOrDefault()?.GetCustomAttribute<DescriptionAttribute>();
return attribute ?.Description ?? value.ToString();
}
public static object GetValueFromDescription(string description, Type enumType)
{
return Convert.ChangeType(LookupDescription(description,enumType),enumType);
}
public static T GetValueFromDescription<T>(string description) where T: struct
{
return (T)LookupDescription(description, typeof(T));
}
private static object LookupDescription(string description, Type enumType)
{
if(!enumType.IsEnum)
throw new ArgumentException("Type provided must be an Enum", enumType.Name);
foreach(var field in enumType.GetFields())
{
var attribute = Attribute.GetCustomAttribute(field, tyepof(DescriptionAttribute)) as DescriptionAttribute;
if((attribute != null && attribute.Description == description)
|| field.Name == description)
{
return field.GetValue(null);
}
}
throw new ArgumentException($"Requested value for '{description}' in enum {enumType.Name} was not found", nameof(description));
}
}
我的JSON覆盖使控制器能够将枚举转换为字符串
//Startup.cs
services.AddMvc().SetCompatibilityVersion(Compatibility.Version_2_2)
.AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new StringAnnotationEnumConverter());
});
public class StringAnnotationEnumConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
var value = token.ToString();
if(reader.TokenType == JsonToken.String)
return EnumExtensions.GetValueFromDescription(value, objectType);
else
return base.ReadJson(reader, objectType, existingValue, serializer);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if(value == null)
{
writer.WriteNull();
return;
}
Enum e = (Enum)value;
string enumName = e.ToDisplayString();
if(string.IsNullOrWhiteSpace(enumName))
throw new JsonSerializationException(String.Format("Integer value {0} is not allowed.",e.ToString("D")));
writer.WriteValue(enumName);
}
}
更新2-WebAPI
这是控制器和域对象的示例代码
public class Agency
{
public int Id {get; set;}
public string Name {get; set;}
public AgencyTypes AgencyType {get; set;}
...
}
[ApiController]
public class AgencyController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Agency([FromForm] Agency agency)
{
...
}
}
答案 0 :(得分:2)
您可以尝试覆盖默认的EnumConverter
来进行自定义属性检查
public class MyEnumConverter: EnumConveter {
public MyEnumConverter(Type type) : base(type) {
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
if (value is string) {
var enumString = (string)value;
return EnumExtensions.GetValueFromDescription(enumString, EnumType);
}
return base.ConvertFrom(context, culture, value);
}
}
并使用TypeConverter
属性装饰枚举
[TypeConverter(typeof(MyEnumConverter))]
public enum AgencyTypes {
[System.ComponentModel.Description("Mental Health")]
MentalHealth,
Corrections,
[System.ComponentModel.Description("Drug & Alcohol")]
DrugAndAlcohol,
Probation
}