The class I'm trying to serialize and deserialize (roughly):
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>();
}
}
Previous version without null
-checking, not working either:
class MyDto
{
public string Name { get; set; }
[XmlArray("UniqueNames")]
[XmlArrayItem("string")]
public List<string> UniqueNameStrings { get; set; }
}
Schema generated for this class:
<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>
And the effect of serialization:
<MyDto>
<Name>MyDtoName</Name>
<UniqueNames>
<string>SomeName</string>
<string>SomeOtherName</string>
<!-- ... <-->
</UniqueNames>
</MyDto>
So serialization looks to be working properly, the problem is that when deserializing, XML seems to ignore the string values altogether. This is the calling code:
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);
}
}
The Name
property (as well as all others that I have omitted for simplicity) are properly deserialized, while the UniqueNames
are left empty. I've put a breakpoint at the set
method and I can see that the deserializer invokes it with value
equivalent to an empty List<string>
, as if the <string>
elements did not exist. Since I can't look into the XML code to see what's going on there, I'm stuck. Any ideas on why XmlSerializer ignores the values in the string array? Especially since it had itself serialized the values into this very format, and now can't handle reading it back...
Try this:
[XmlRoot]
public class MyDto
{
[XMLElement]
public string Name { get; set; }
[XmlArray("UniqueNames"), XmlArrayItem("UniqueName")]
public List<string> UniqueNameStrings { get; set; }
public MyDto() { }
}
I can't tell from the example code, but it may be a missing empty class constructor. Also I updated the XmlArrayItem thinking there might be a clash with calling it 'string'.
Give this Serializer a shot:
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;
}
}
}
Example:
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;
}
}
use config.Names
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.