1

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.

ubi
  • 4,041
  • 3
  • 33
  • 50
  • 1
    http://stackoverflow.com/questions/1266547/how-do-you-find-out-when-youve-been-loaded-via-xml-serialization – Eric J. Oct 21 '15 at 23:14
  • How is the deserializer supposed to know how many bytes to read? Would it not be the same number of bytes that was serialized in the first place? – D Stanley Oct 21 '15 at 23:35
  • @DStanley if XML serializer would call some sort of factory to create object the factory can provide some value for that argument in the class. – Alexei Levenkov Oct 21 '15 at 23:38
  • Side note: ubi, since there is no existing way to achieve what you want with approach you've shown, can you add information to you post *why* you trying to do that (or what is your actual goal)? – Alexei Levenkov Oct 21 '15 at 23:39

1 Answers1

1

No, there is no mechanism in XML serialization to provide any sort of factory to create objects instead of default constructor.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179