I'm trying to implement a IXmlSerializable
class which needs to be initialized but as the serialization uses the default constructor, initialization cannot be done. Any hints how it could be done?
Here's an example class. It has an array and when deserialized it has to copy/decode only a fixed number of bytes from the XML file. Initialization is needed to tell it what that fixed number is.
public class XmlByteArray : IXmlSerializable
{
public Byte[] Values;
// serialization will use this constructor so Values won't be instantiated
public XmlByteArray()
{
}
// Values array needs to be instantiated
public XmlByteArray(int size)
{
Values = new Byte[size];
}
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
var str = reader.ReadString();
reader.ReadEndElement();
// decode str into a Byte array
Byte[] v = Enumerable.Range(0, str.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(str.Substring(x, 2), 16))
.ToArray();
Array.Copy(v, Values, Values.Length);
}
public void WriteXml(XmlWriter writer)
{
var str = BitConverter.ToString(Values).Replace("-", "");
writer.WriteString(str);
}
}
If this was c++ I'd think to solve this by making XmlByteArray
a template that takes an int
type but that's not allowed in c#.
To add more details as requested in the comments, what I'm trying to do is use the objects of XmlByteArray
in another class and read a file like this
<SomeClass>
<memberA>blah blah</memberA>
<memberB>0A0B0C0D</memberB>
<memberC>0A0B0D</memberC>
</SomeClass>
The serialized class would be
public class SomeClass
{
public SomeClass()
{ }
public string memberA = "";
public XmlByteArray memberB = new XmlByteArray(2);
public XmlByteArray memberC = new XmlByteArray(3);
}
After deserialization memberB.Values
should have {0x0A, 0x0B}
not {0x0A, 0x0B, 0x0C, 0x0D}
. The serialized file is meant be edited manually so the deserialized data could be inconsistent with how the program serializes them.
PS. On a side note I had to add a ReadEndElement()
call to ReadXml()
to get the reading right though this MSDN example doesn't have it. Not sure why it was needed.