c# - 在 WebAPI 中实现一个 TypeConverter 来对 Enum 进行描述
问题描述
我DescriptionAttribute
在 Enums 上使用来提供包含空格的描述。我创建了一些扩展方法,它们将返回枚举的字符串描述和/或从字符串描述返回枚举值。
现在我希望我的 WebAPI 使用这些扩展方法来处理枚举类型转换而不是默认的 TypeConverter,以便我可以传递一个类似的值"Car Wash"
并将其映射到一个枚举。
有没有办法将默认字符串覆盖为 Enum TypeConverter?
环境 .NetCore 2.x
更新 - 我当前的代码
当控制器将对象序列化为 JSON 以发送到客户端时,我当前的代码效果很好。鉴于以下Enum
情况,枚举值为 0 将导致客户端获得字符串“心理健康”——完美。但是,现在当客户端将“心理健康”发送回服务器时——我需要将其转换回AgencyTpes.MentalHealth
. 现在,绑定引擎抛出一个错误。
//Example Enum
public enum AgencyTypes {
[Description("Mental Health")]
MentalHealth,
Corrections,
[Description("Drug & Alcohol")]
DrugAndAlcohol,
Probation
}
我使用的枚举扩展DescriptionAttribute
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)
{
...
}
}
解决方案
您可以尝试覆盖默认值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
}
推荐阅读
- jquery - 如何修复引导下拉菜单隐藏的溢出?
- opayo - 版本 4.0 localhost 测试得到 3228:ThreeDSNotificationURL 字段格式无效
- windows - 在没有融合的情况下创建 Kafka 连接
- blazor - 切换 asp.net Core Blazor 托管模型
- python - 问题正则表达式,如何使用搜索表单处理带有可选参数的多个查看 URL
- svg - SVG 路径未缩放以适应视口
- vb.net - 如何使用带有绑定数据集的 VS19 获取父记录的 Scope_identity 值
- mysql - 如何使用触发器 mysql 更新表
- r - R - 找出包含行最大值的列是否与另一列绑定
- python - ValueError:在将数据拟合到 svm 时设置具有序列的数组元素