实施一个用于描述以在WebAPI中枚举的描述



我在枚举上使用DescriptionAttribute来提供包括空格的描述。我创建了一些扩展方法,该方法将返回枚举的字符串描述和/或从字符串描述中返回枚举值。

现在,我希望我的WebAPI使用这些扩展方法来处理枚举类型转换,而不是默认的TypeConverter,以便我可以传递像"Car Wash"这样的值并将其映射到枚举。

有没有办法将默认字符串覆盖到枚举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

这是控制器的示例代码&amp;域对象

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
}

最新更新