George2
George2

Reputation: 45801

customize deserialization sample in C#?

I am looking for a sample, which could let me deserialize an XML stream encoded in UTF-8 into a field of a class. More specifically, I have a class like,

class Foo
{
    string abc;
    byte[] bcd;
}

and abc maps to XML element "Abc" and bcd maps to XML element "Bcd", and I want to get the stream for bcd and retrieve bytes (from XML stream for related element "Bcd" directly) to manipulate manually/in a customized way.

I am looking for a sample, but failed, could anyone help to point me to a related sample or wrote some pseudo code?

Edit: the XML is SOAP reaponse from server, in the response there is one response XML element (element Bcd in my sample) which is encoded by UTF-8 from server side, but since Http Web Services will use base64 at client side, so each time I receive such "bytes" at client side and the automatically generated web services proxy will throw exception says invalid XML element in base64 encoding. So, I am thinking about how to overwrite the default using base64 encoding to decode the bytes, and this is why I ask this question. If there could be a way to accept stream or something similar represents the on-wire bytes of the related response elements (Bcd in my sample) and let me manipulate, it will be so great!

thanks in advance, George

Upvotes: 2

Views: 3613

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1064114

IXmlSerializable is one option (but not much fun), but it feels like in this case properties offer most of what is wanted without extra work:

[Serializable]
public class Foo
{
    public string Abc {get;set;}
    private byte[] bcd;
    public byte[] Bcd {
        get {return bcd;}
        set {/* your code (with `value`) here */ }
    }
}

Re the wire format (base64 etc); have you tried just running it through xsd.exe? It might surprise you and get it right... but yes; within IXmlSerializable you will have your choice of ReadContentAsBase64, ReadContentAsBinHex, etc. But it is very ugly; something like (for a simple version):

[Serializable]
public class Foo : IXmlSerializable
{
    public Foo() { }
    public Foo(string abc, byte[] bcd)
    {
        Abc = abc;
        Bcd = bcd;
    }
    public string Abc { get; private set; }
    public byte[] Bcd { get; private set; }

    XmlSchema IXmlSerializable.GetSchema()
    {
        return null;
    }

    void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
    {
        if (Abc != null)
        {
            writer.WriteElementString("Abc", Abc);
        }
        if (Bcd != null)
        {
            writer.WriteStartElement("Bcd");
            writer.WriteBase64(Bcd, 0, Bcd.Length);
            writer.WriteEndElement();
        }
    }
    void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
    {
        reader.ReadStartElement();
        reader.ReadStartElement("Abc");
        Abc = reader.ReadString();
        reader.ReadEndElement();
        reader.ReadStartElement("Bcd");
        MemoryStream ms = null;
        byte[] buffer = new byte[256];
        int bytesRead;
        while ((bytesRead = reader.ReadContentAsBase64(
            buffer, 0, buffer.Length)) > 0)
        {
            if (ms == null) ms = new MemoryStream(bytesRead);
            ms.Write(buffer, 0, bytesRead);
        }
        if (ms != null) Bcd = ms.ToArray();
        reader.ReadEndElement(); 
    }
}

Upvotes: 3

Related Questions