首页 > 解决方案 > 抽象基类列表仅返回基类的属性

问题描述

我有一个与此类似的模型设置。从抽象基类继承的两个类。

// Models
public abstract class Transaction 
{
    // Shared Properties..
}
public class TransactionType1 : Transaction
{
    public int TxType1Prop { get; set;}
}
public class TransactionType2 : Transaction
{
    public int TxType2Prop { get; set;}
}

在我的 API 中,我有一个“基类”列表,我用不同的事务类型填充它。当我在返回一切看起来不错之前进行调试时,会填充各个属性等。

// Ctrl
public IAtionResult GetTransactions()
{
    var transactions = new list<Transaction>() 
    {
        new TransactionType1(),
        new TransactionType2() 
    }
    return Ok(transactions);
} 

但是当 Api 调用返回到 swagger 时,只包含来自基类的共享属性。

IE TxType1Prop&TxType2Prop不包含在结果中。

是否只能在内存中使用这些属性,或者我可以让我的结果也包含它们?

标签: c#.net-core

解决方案


不幸的是,您不能在带有“开箱即用”序列化程序的接口处使用通用基类[这是用于“开箱即用”设置的 - 正如 Ben 提到的,有一些方法可以解决它]。您可以提供一个自定义的 JSON 序列化程序,它可能能够处理这个问题。在我的选择中,即使它正在工作,它也不是最干净的解决方案,因为:

  1. 您正在公开有关您的应用程序的内部信息(如序列化程序)
  2. 你放大你的 JSON
  3. 你降低了可读性
  4. API 是关于合约的,多态性在一定程度上打破了这一点

您可以在此处阅读有关 API 多态性的更多信息。

在我看来,最好的方法是使用另一种类型的类作为传输对象,它由主要属性和额外的“额外属性”(子类属性)的键值集组成,使用这种方法,你可以发送所有需要的信息(也许你想添加类型信息以便在客户端处理)。

public class TransactionTransport {
   // other attributes ommited

   // attribute name / attribute value
   Map<String, Object> AdditionalValues {get; set;}
}

在这种情况下,您需要AdditionalValues在 API 中填写子类的属性(将子类映射到TransactionTransport),一切顺利。

这也会略微降低可读性,但 JSON 中不需要的内容会减少很多。此外,您不会将任何内部的东西暴露在野外。


推荐阅读