【问题标题】:Api that received generic type接收泛型类型的 API
【发布时间】:2020-11-02 22:19:48
【问题描述】:

这样做的正确方法是什么。例如,我有一个处理车辆的 api。我想要一个保存和获取车辆的 POST 和 GET 端点。但是车辆可以是汽车、公共汽车或卡车。具有不同的属性。但在我的数据库中,它们是车辆类型,根据 VehcileTypeId,连接到 Car、Bus 或 Truck 表。

在代码中,Bus caked 继承自带有公共字段的 Vehicle 类。但是 Bus 类有额外的属性。

有没有办法让 SaveVehicle 端点接受车辆类型?但是是否从 UI 提交了字段?还是我需要 SaveBus、SaveCar、SaveTruck 端点?

我不确定我的请求对象可能是什么。

公共异步任务保存(GenricVehicleRequest 请求)

【问题讨论】:

    标签: c# asp.net-core asp.net-core-webapi


    【解决方案1】:

    从 REST 角度来看,您最好使用单独的 SaveBus、SaveCar 和 SaveTruck 端点,否则您会丢失自我描述和资源标识(尽管可以讨论) 但是如果你真的需要这个,你可以这样做,而且它是由 Swagger (OpenAPI) 支持的,这个特性被称为多态性 (surprise-surprise) - https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/

    如何在.NET中实现:

    在您的基类中,您需要一个鉴别器属性,稍后您将通过它来决定在您的自定义 json 转换器中使用什么真实类型:

    public class Vahicle
    {
        public string Discriminator {get;set;}
        ...
    }
    

    然后您创建自己的自定义 JSON 转换器:

    public class VahicleConverter : JsonConverter
    {
        private string _discriminator { get; set; } = "Discriminator";
    
        public VahicleConverter ()
        {
    
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null) return null;
    
            var jDerivedObject = JObject.Load(reader);
    
            var discriminator = jDerivedObject.Value<string>(_discriminator);
            if (string.IsNullOrWhiteSpace(discriminator))
                throw new Exception("Invalid discriminator value");
    
            var derivedType = objectType;
            switch(discriminator)
            {
                case "Bus":
                    derivedType = typeof(Bus);
                case "Truck ":
                    derivedType = typeof(Truck);
                default:
                    throw new Exception("Unknown type");
            }
    
            var derivedObject = Activator.CreateInstance(derivedType);
    
            serializer.Populate(jDerivedObject.CreateReader(), derivedObject);
    
            return derivedObject;
        }
    
        public override bool CanConvert(Type objectType) => true;
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    
        //Not required
        public override bool CanWrite => false;
    }
    

    然后您需要指示 .NET JSON 序列化程序使用您的自定义序列化程序,只需将 [JsonConverter(typeof(VahicleConverter))] 属性添加到您的类:

    [JsonConverter(typeof(VahicleConverter))]
    public class Vahicle
    {
        public string Discriminator {get;set;}
        ...
    }
    

    现在您可以使用 API 操作,例如:

    [HttpPost]
    public Task<Result> AddVahicle([FromBody]Vahicle model)
    

    并使用包含您的鉴别器的 JSON 请求您的操作:

    {
       Dicriminator:"Bus",
       BusSpecificProp:"1",
       ...
    }
    

    对不起,如果上面的代码有一些拼写错误,我没有运行这个确切的代码,但我过去使用过类似的代码,是的,额外的荣誉归于这个答案 - https://stackoverflow.com/a/51815457/7064030

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-21
      • 2016-10-16
      • 1970-01-01
      相关资源
      最近更新 更多