【问题标题】:c# REST API polymorphic return typec# REST API 多态返回类型
【发布时间】:2017-07-12 11:13:44
【问题描述】:

我创建了如下具有继承性的数据合约:-

[DataContract(Name = "Animal")]
public class Animal { ... }

[DataContract(Name = "Dog ")]
public class Dog : Animal { // Has some Dog specific member properties }

[DataContract(Name = "Cat ")]
public class Cat : Animal { // Has some Cat specific member properties }

我正在使用 ASP.NET WebApi 来提供 REST API,例如:

[HttpGet]
public Task<Animal> Get(string type) 
{ 
    switch(type)
    {
        case "dog":
            Dog dog = GetDogDetails();
            return Task.FromResult(dog);
            break;

        case "cat":
            Cat cat = GetCatDetails();
            return Task.FromResult(cat);
            break:
    }
}

我无法退回相应的动物类型。我收到以下错误:- “不能将 Dog 隐式转换为 Animal”。

根据 REST API 标准,这种多态响应也是一件好事。

【问题讨论】:

  • 无论如何,这是一个可怕的错误信息。
  • 如果您使用 JSON,请忘记数据合约的噩梦,只需从控制器返回 dynamic。然后您可以返回任何内容,并将其序列化(尽可能)给客户端。
  • @zaitsman 如果需要,我不建议使用动态响应,如 VladStryapko 在他的回答中所说的那样使用 IHttpActionResult。
  • @FilipCordas 为什么? Ihttpactionresult 要求您将响应包装在对 this.Ok() 和类似的调用中。这是不必要的代码混乱。无论如何,您的单元测试应该确保行为。这种方法的唯一限制是默认的 xml 序列化无法解决这个问题。但我过去在商业上使用它非常成功。
  • @zaitsman 这是一种观点,但对我来说,这只是尖叫缺乏架构。 dynamic 的返回等效于从控制器返回一个object。假设有人服用 case:1 return new { A="" }; case 2 : return Ok(new { A="" }); 这将编译并返回相同的 JSON 值。并且编译时异常总是比运行时更好。

标签: c# inheritance asp.net-web-api polymorphism response


【解决方案1】:

您收到此错误的原因是因为您返回 Task&lt;T&gt; 并且任务不是协变的。也就是说,即使DogAnimalTask&lt;Dog&gt; 也不是Task&lt;Animal&gt;

你能做什么?

  1. 把你的代码改成

        case "dog":
        Animal dog = GetDogDetails();
        return Task.FromResult(dog);
        break;
    

你会失去狗的特定属性。

  1. 利用Task&lt;IHttpActionResult&gt; 并返回Ok(yourObject)

    [HttpGet]
    public async Task<IHttpActionResult> Get(string type) 
    { 
        switch(type)
        {
            case "dog":
                Dog dog = GetDogDetails();
                return Ok(dog);
                break;
    
        ...
        }
    }
    

我认为你应该走第二条路。

第二点,我真的看不出有什么理由在这里使用async/await。为什么要使用Task.FromResult?如果您的GetDogDetails 方法是async,请考虑awaiting。我认为您不必担心当前代码中的任务。

根据 REST API 标准,这种多态响应也是一件好事。

我不了解正式标准,但一般来说,某些对象具有某些属性而其他对象不具有某些属性是可以的。例如,想象一个支付系统返回一个抽象事件,该事件可能有也可能没有相关联的发票。

【讨论】:

  • 您的回答很好我只想补充一点,当您进行任何类型的自动代码构建(例如创建文档)时,多态响应可能会成为问题。此外,根据序列化程序配置,您可能会开始在 JSON 中看到 $type 属性。这一切都可以解决,但会产生问题。
  • @FilipCordas 是的,我认为在可选属性的情况下,我更愿意简单地将它们放在一个类中并将null 序列化为任何内容或 API 的客户更喜欢的东西(如果它是一个内部 API,您可以与他们通信)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-19
  • 1970-01-01
  • 2010-09-19
  • 2019-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多