Search code examples
c#xmlxml-serializationxmlserializerixmlserializable

Using IXmlSerialization, how can I serialize a T property?


My question is so simple.

Imagine we have a Foo class. and has a T property.

public class Foo<T>
{
    public T Property { get; set; }
}

I want to implement in it IXmlSerializable and my problem is I have no idea to imitate the standard XmlSerialization. I really have no idea about how to write this property like the standart XmlSerlalization.

UPDATE: I did this and it's not working

public class Foo<T> : IFoo
    where T : IXmlSerializable
{
    public T Value { get; set; }
}

public class FooA : Foo<string> { }
public class FooB : Foo<int> { }
public class FooC : Foo<List<Double>> { }

When I serialized this classes (A, B and C). I wanna have something like this:

Using first class:

<FooA>
    <Value>StringDemo</Value>
</FooA>

Using second class:

<FooB>
    <Value>2</Value>
</FooB>

Using third class:

<FooC>
    <Value>
        <ArrayOfDouble xsi:..>
            <Double>3.1416</Double>
            <Double>4.2</Double>
        </ArrayOfDouble>
    </Value>
</FooC>

Something like this is what I wanted, I don't want to implement in all of this a custom XmlSerializer, I mean the default which the standard serialization use.


Solution

  • You would need to implement IXmlSerializable in Foo<T>, and T (using where T : IXmlSerializable. The implementation in Foo<T> would then be responsible for writing a wrapper element with type information (in WriteXml) and call WriteXml on T, and recreate the instance from the type information (in ReadXml) and call ReadXml on T.

    Basic types like String and Double is not IXmlSerializable, so you cant have where T : IXmlSerializable if you want to support them. You can also provide default implementations of ReadXml and WriteXml. This works since you need to create a Foo<T> before calling ReadXml, forcing you to know T.

    public class Foo<T> : IXmlSerializable {
        public T Value { get; set; }
    
        XmlSchema IXmlSerializable.GetSchema() {
            return GetSchema();
        }
    
        protected virtual XmlSchema GetSchema() {
            return null;
        }
    
        public virtual void ReadXml(XmlReader reader) {
            reader.ReadStartElement();
            var xmlSerializer = new XmlSerializer(typeof(T));
            Value = (T)xmlSerializer.Deserialize(reader);
            reader.ReadEndElement();
        }
    
        public virtual void WriteXml(XmlWriter writer) {
            var xmlSerializer = new XmlSerializer(typeof(T));
            xmlSerializer.Serialize(writer, Value);
        }
    }