基类和继承类的 XML 序列化信息

Posted

技术标签:

【中文标题】基类和继承类的 XML 序列化信息【英文标题】:XML Serializing information on Base class and inherited class 【发布时间】:2020-04-16 20:24:51 【问题描述】:

我正在尝试将 C# 对象序列化为 XML,以便它可以用作 API 调用的主体。他们对所需的输入非常挑剔。我已经构建了以下类来保存我需要发送给他们的数据。包括属性和所有属性作为元素而不是属性。他们还要求列表包含type="array",尽管创建我自己的类来实现 List 是最简单的,因为我给它们的所有列表都必须具有相同的属性。当发生序列化时,它会序列化 List 项的基类,但它不包括我想要的派生类的属性。

public class CustomArray<T> : List<T>

    [XmlAttribute]
    public string type  get; set;  = "array";


[XmlRoot("message")]
public class MessageBody

    [XmlArray("Checks"), XmlArrayItem("CheckItem")]
    public CustomArray<Check> CheckList  get; set; 


public class Check

    [XmlElement("C_CHECK_NUMBER")]
    public string CheckNumber  get; set; 

    [XmlElement("C_CHECK_AMOUNT")]
    public decimal Amount  get; set; 

    [XmlArray("InvoiceList"), XmlArrayItem("Invoice")]
    public CustomArray<Invoice> InvoiceList  get; set; 


public class Invoice

    [XmlElement("C_INVOICE_ID")]
    public long ID  get; set; 

    [XmlElement("C_INVOICE_NUM")]
    public string InvoiceNum  get; set; 

然后我运行这段代码:

// Create a sample object
var message = new MessageBody()

    CheckList = new CustomArray<Check>
    
        new Check
        
            CheckNumber = "111",
            Amount = 1.00M
        ,
        new Check
        
            CheckNumber = "112",
            Amount = 2.00M,
            InvoiceList = new CustomArray<Invoice>
            
                new Invoice
                
                    ID = 1,
                    InvoiceNum = "1"
                
            
        
    
;

// Create custom settings
var settings = new XmlWriterSettings

    OmitXmlDeclaration = true,
    Indent = true
;

// Serialize item and print it to console
using (var sw = new StringWriter())
using (var writer = XmlWriter.Create(sw, settings))

    var serializer = new XmlSerializer(message.GetType());
    serializer.Serialize(writer, message, new XmlSerializerNamespaces(new[]  XmlQualifiedName.Empty ));
    Console.WriteLine(sw.ToString());

我把这个写到控制台:

<message>
  <Checks>
    <CheckItem>
      <C_CHECK_NUMBER>111</C_CHECK_NUMBER>
      <C_CHECK_AMOUNT>1.00</C_CHECK_AMOUNT>
    </CheckItem>
    <CheckItem>
      <C_CHECK_NUMBER>112</C_CHECK_NUMBER>
      <C_CHECK_AMOUNT>2.00</C_CHECK_AMOUNT>
      <InvoiceList>
          <Invoice>
              <C_INVOICE_ID>1</C_INVOICE_ID>
              <C_INVOICE_NUM>1</C_INVOICE_NUM>
          </Invoice>
      </InvoiceList>
    </CheckItem>
  </Checks>
</message>

但我需要得到这个:

<message>
  <Checks type="array">
    <CheckItem>
      <C_CHECK_NUMBER>111</C_CHECK_NUMBER>
      <C_CHECK_AMOUNT>1.00</C_CHECK_AMOUNT>
    </CheckItem>
    <CheckItem>
      <C_CHECK_NUMBER>112</C_CHECK_NUMBER>
      <C_CHECK_AMOUNT>2.00</C_CHECK_AMOUNT>
      <InvoiceList type="array">
          <Invoice>
              <C_INVOICE_ID>1</C_INVOICE_ID>
              <C_INVOICE_NUM>1</C_INVOICE_NUM>
          </Invoice>
      </InvoiceList>
    </CheckItem>
  </Checks>
</message>

感谢您的帮助!

这是我为了炫耀而制作的 dotnetfiddle。这并不准确,但它具有相同的想法。 https://dotnetfiddle.net/ALCX5H

【问题讨论】:

【参考方案1】:

尝试以下:

[XmlRoot("message")]
public class MessageBody

    [XmlElement("Checks")]
    public Checks Checks  get; set; 

public class Checks

    [XmlAttribute]
    public string type  get; set; 

    [XmlElement("Checks")]
    public List<Check> Checks  get; set; 


public class Check

    [XmlElement("C_CHECK_NUMBER")]
    public string CheckNumber  get; set; 

    [XmlElement("C_CHECK_AMOUNT")]
    public decimal Amount  get; set; 

【讨论】:

这会起作用,但它需要我为用于此 API 的每个列表创建一个新类。我有另一个嵌入在 Check 类中的列表,我希望每次都使用一个通用类。我感觉在完成更多测试后这是不可能的,因为序列化程序正在查看属性以查看它是否实现了 IEnemurable 和泛型,如果实现了,它开始序列化泛型项并且不关心其他任何项自定义列表类的属性。 @JDB - 你必须描述/举例说明那个额外的“列表”是什么。根据此,可以调整/扩展上述内容。 在一个检查项目中,我也可能有一个List&lt;Invoice&gt;。通过上述实现,我还必须有一个用于包装 Invoices 的类。我希望我可以有一个通用的特殊列表类,我可以在需要列表的任何时候调用它。让它工作并非不可能,它只是不是最干净的解决方案。我担心它可能是唯一的解决方案,所以我可以让它工作。我将用另一个场景编辑原始问题。

以上是关于基类和继承类的 XML 序列化信息的主要内容,如果未能解决你的问题,请参考以下文章

XML 序列化和继承类型

C++基类和派生类的构造函数

C++中的基类和派生类

基类和继承类的类型注释 - Generic 和 TypeVar 是正确的方法吗?

生成一个派生类对象时,调用基类和派生类构造函数按啥次序

C++入门派生类和基类的构造/析构函数关系