XmlSerializer不会序列化派生值

后端开发 2026-07-09

(代码示例基于.NET 8)

我有一个 XmlSerializer,它应该给出一个小数的格式化版本(仅保留两位小数)。但当我运行这里显示的代码时,字段 IAmStringIAmAlsoString 被完全忽略。为了完整起见:在 ToString() 中移除 "c2" 并不会改变结果。

using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApp3;

[XmlRoot(Namespace = "urn:iso:std:iso:20022:tech:xsd:pain.008.001.08")]
public class DecimalTestCase
{
    [XmlElement("IAmDecimal")]
    public decimal Value { get; set; }

    [XmlElement("IAmString")]
    public string AmountAsString => Value.ToString("c2");

    [XmlElement("IAmAlsoString")]
    public string AnotherTry
    {
        get
        {
            return Value.ToString("c2");
        }
    }
}

public class Run
{
    public static void Main()
    {
        SerializeObject("DecimalToString.xml");
    }

    public static void SerializeObject(string filename)
    {
        XmlSerializer mySerializer = new(typeof(DecimalTestCase));

        TextWriter writer = new StreamWriter(filename);
        DecimalTestCase myDecimalTestCase = new()
        {
            Value = 123.1234m
        };

        mySerializer.Serialize(writer, myDecimalTestCase);
        writer.Close();
    }
}

我得到的结果是:

<?xml version="1.0" encoding="utf-8"?>
<DecimalTestCase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.08">
  <IAmDecimal>123.1234</IAmDecimal>
</DecimalTestCase>

现在我已经完全不知道该尝试什么。甚至连弄清楚序列化器为何忽略这两个输出的逻辑都不知道。

这真的就是确保小数只输出两位的正确做法吗?还是有更好的办法?

解决方案

原因是这些属性是只读的。

来自 https://learn.microsoft.com/en-us/dotnet/standard/serialization/introducing-xml-serialization:

XML序列化不会转换方法、索引器、私有字段,或只读属性(除了只读集合)。要序列化对象的所有字段和属性(包括公有和私有的),请改用DataContractSerializer而不是XML序列化。

如果你为第二个属性添加一个抛出异常的setter,例如

[XmlElement("IAmAlsoString")]
public string AnotherTry
{
    get => Value.ToString("c2");
    set => throw new InvalidOperationException();
}

那么 IAmAlsoString 会被包含在输出中。

就个人而言,我从来不是 XmlSerializer 的铁粉——使用LINQ to XML时,编写自定义序列化/反序列化代码其实相当直接,这样你就不需要担心像这样的怪异之处。诚然,我也从来没有需要对一大批类型这么做过——但如果你只有相对较少的类型,编写 FromXElement 静态方法和 ToXElement 实例方法其实也相当直接,并且它会让你获得完全的控制。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章