【问题标题】:XmlSerializer does not deserialize a List<string>XmlSerializer 不反序列化 List<string>
【发布时间】:2018-08-25 14:01:14
【问题描述】:

我正在尝试序列化和反序列化的类(大致):

class MyDto
{
    public string Name { get; set; }

    private List<string> _uniqueNameStrings = new List<string>();

    [XmlArray("UniqueNames")]
    [XmlArrayItem("string")]
    public List<string> UniqueNameStrings 
    { 
       get => _uniqueNameStrings; 
       set => _uniqueNameStrings = value ?? new List<string>(); 
    }
}    

没有null-checking 的先前版本,也无法正常工作:

class MyDto
{
    public string Name { get; set; }

    [XmlArray("UniqueNames")]
    [XmlArrayItem("string")]
    public List<string> UniqueNameStrings { get; set; }
}

为此类生成的架构:

<xs:complexType name="MyDto">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" name="Name" nillable="true" type="xs:string" />
        <xs:element minOccurs="0" maxOccurs="1" name="UniqueNames" type="ArrayOfString" />
    </xs:sequence>
</xs:complexType>
<xs:complexType name="ArrayOfString">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="xs:string" />
    </xs:sequence>
</xs:complexType>

以及序列化的效果:

<MyDto>
    <Name>MyDtoName</Name>
    <UniqueNames>
        <string>SomeName</string>
        <string>SomeOtherName</string>
        <!-- ... <-->
    </UniqueNames>
</MyDto>

所以序列化看起来工作正常,问题是在反序列化时,XML 似乎完全忽略了字符串值。这是调用代码:

using System.IO.Abstractions;

private IFileSystem _fileSystem;

public void SerializeDto(object dto, string filePath)
{
    var serializer = new XmlSerializer(dto.GetType());

    using (var streamWriter = _fileSystem.FileStream.Create(filePath, FileMode.Create, FileAccess.Write))
    {
        serializer.Serialize(streamWriter, dto);
        streamWriter.Flush();
    }
}

public T DeserializeDto<T>(string filePath) where T : class
{
    var serializer = new XmlSerializer(typeof(T));

    using (var streamReader = _fileSystem.FileStream.Create(filePath, FileMode.Open, FileAccess.Read))
    {
        return (T) serializer.Deserialize(streamReader);
    }
}

Name 属性(以及我为简单起见省略的所有其他属性)已正确反序列化,而UniqueNames 则留空。我在set 方法处设置了一个断点,我可以看到反序列化程序使用value 调用它,相当于一个空的List&lt;string&gt;,就好像&lt;string&gt; 元素不存在一样。由于我无法查看 XML 代码以了解那里发生了什么,所以我被卡住了。关于为什么 XmlSerializer 忽略字符串数组中的值的任何想法?特别是因为它本身已经将值序列化为这种格式,现在无法处理读取它......

【问题讨论】:

  • 如果将元素名称更改为string 以外的其他名称,是否有效?
  • 不。将元素名称更改为UniqueName 后仍为value.Count = 0
  • 如果您将UniqueNameStrings 属性更改为string[]
  • 现在可以了,谢谢!但是您知道为什么List&lt;string&gt; 以一种方式工作,而另一种则不行吗?
  • 我无法在 .NET Framework 4.7 或 4.5.1 中重现这一点,正如 @ParrishHusband 所说,请同时添加您的序列化代码。

标签: c# .net xml xmlserializer


【解决方案1】:

试试这个:

[XmlRoot]
public class MyDto
{
    [XMLElement]
    public string Name { get; set; }

    [XmlArray("UniqueNames"), XmlArrayItem("UniqueName")]
    public List<string> UniqueNameStrings { get; set; }

    public MyDto() { }
}

我无法从示例代码中看出,但它可能是缺少空类构造函数。此外,我更新了 XmlArrayItem,认为将其称为“字符串”可能会发生冲突。

试试这个序列化器:

public static void Serialize<T>(T t, string filePath, bool overwrite = true)
{
    using (var fs = new FileStream(filePath, overwrite ? FileMode.Create : FileMode.CreateNew, FileAccess.Write))
    {
        var serializer = new XmlSerializer(typeof(T));
        var ns = new XmlSerializerNamespaces();
        ns.Add("", ""); // Omits xmlns:xsi/xmlns:xsd

        try
        {
            serializer.Serialize(fs, t, ns);
        }
        catch (System.Exception)
        {
            if (File.Exists(filePath))
                File.Delete(filePath);

            throw;
        }
    }
}

【讨论】:

  • 对不起,它不起作用。注意 - 空 ctor 隐含地存在(没有指定 ctor,因此会自动生成一个空的)。
  • @V0ldek 啊,对 ctor 来说是这样。抓住稻草,因为到目前为止一切看起来都很好。你能发布你的序列化代码吗?
  • 我也添加了序列化。
  • 通用版本看起来更好,所以我会保留它,但它没有帮助。输出没有改变,除了命名空间,反序列化仍然给出相同的结果。
【解决方案2】:

例子:

XML:

<Names>
    <Names>John</Names>
    <Names>Doe</Names>
    <Names>Martin</Names>
    <Names>Looter</Names>
</Names>

C#:

public class Configuration
{
    [XmlArray("Names")]
    [XmlArrayItem("Names")]
    public List<string> Names { get; set; }

    public Load(Stream stream) 
    {
        var xmlSerializer = new XmlSerializer(typeof(Configuration));
        var config = (Configuration)xmlSerializer.Deserialize(stream);
        return config;
    }

}

使用 config.Names

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-18
    • 2014-02-08
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-22
    相关资源
    最近更新 更多