16

I have a scenario in which I have a class Resource which has two other classes nested in it; Action and ResourceURL. I need to write custom xmlserializer for Resource and Action but not for ResourceURL. I implemented IXmlSerializable for both.

The problem is, when Resource is serialized, i call the Action.WriteXML(XmlWriter) to get the serialized form of Action, but i can't get serialized form of ResourceURL. The tags become all messed up and it also adds an tag.

So how do i serialize an object which has customer serilzation for some nested objects but not for others?

Steve B
  • 36,818
  • 21
  • 101
  • 174
Sheikh Usman
  • 327
  • 1
  • 5
  • 12

1 Answers1

23

Here is a sample WriteXml method:

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        // Simple string value:
        writer.WriteAttributeString("Name", this.Name);

        // Object without IXmlSerializable implementation:
        writer.WriteStartElement("NonCustomObject");
        new XmlSerializer(NonCustomObjectType).Serialize(writer, this.NonCustomObject);
        writer.WriteEndElement();

        // Object with IXmlSerializable implementation:
        writer.WriteStartElement("CustomObject");
        (this.CustomObject as IXmlSerializable).WriteXml(writer);
        writer.WriteEndElement();
    }

Here is a corresponding ReadXml method:

    void IXmlSerializable.ReadXml(XmlReader reader)
    {
        // Simple string value
        this.Name = reader.GetAttribute("Name");

        // Object without IXmlSerializable implementation here:
        reader.ReadStartElement();
        if (reader.Name == "NonCustomObject")
        {
            reader.ReadStartElement();
            this.NonCustomObject = new XmlSerializer(NonCustomObjectType).Deserialize(reader);
            reader.ReadEndElement();
        }

        // Object with IXmlSerializable implementation here:
        reader.ReadStartElement();
        if (reader.Name == "CustomObject")
        {   
            (this.CustomObject as IXmlSerializable).ReadXml(reader);
            reader.ReadEndElement();
        }
    }
Sean Allison
  • 346
  • 3
  • 4
  • `Deserialize()` returns `object` as a type - you need to cast to get the correct type (this is where C++ templates and Java generics win). – Guss Oct 19 '13 at 13:23
  • @Guss how so? .NET generics are vastly superior to Java generics due to CLR support. C++ templates are even worse as they require the compilation of all possible variants in advance. – Mr. TA Dec 04 '17 at 20:36
  • @Mr.TA - (a) you didn't dispute the problem I specified, and that is a serious glaring problem in .Net; (b) I don't understand what CLR has to do with it - generics are supposed to help you during compilation, there's no reason to keep the information after that - its basically "safe casting" help; (c) your assertion on C++ is incorrect: C++ templates are compiled only for the types actually in use. – Guss Dec 05 '17 at 08:22
  • @Guss (a) the problem you specified doesn't even exist; any deserialization method will always create the type using reflection or a similar mechanism, not using native `new` operator, therefore whether it returns `T` or `object` is irrelevant, since it'll have to be cast either inside or outside the method. (b) CLR has everything to do with it, because it provides native support for generic types, reducing casts and boxing/unboxing conversions, plus a myriad of other benefits, such as reflection support for generics. (c) exactly, so in a program which has `List<>` of 15 types, there is bloat. – Mr. TA Dec 06 '17 at 13:41
  • @Mr.TA: (a) its very different if the framework implements the casting internally according to the generic type than if every developer has to cast correctly manually. If you don't see that there are different requirements for platform code than for user code then we have nothing to discuss. (b) The only thing you said that made sense was "reflection support", which is not a problem in Java if you set a retention policy. (c) what you call "bloat", C++ calls "efficient run-time with predictable time complexity" - to each their own ;-) – Guss Dec 07 '17 at 09:16
  • @Guss (a) it's a minor difference, more of a convenience; .NET doesn't have it for `XmlSerializer` because it was developed before .NET had generics; and .NET perfectly supports creating methods like that now; are you disappointed in the whole framework because of one legacy method signature? (b) reduced conversions/casts/boxings makes no sense? well you should read a book or two. Also it's better if the reflection info is available all the time, not just "if you do something". (c) I love C++ and its overall efficiency, but templates in particular have this inefficient trait to them. – Mr. TA Dec 08 '17 at 11:16
  • @Mr.TA - I'm amused that you think that having more type information in the runtime magically reduces casting costs somehow. May all your programs run as fast as you expect them to. – Guss Dec 11 '17 at 07:28
  • @Guss I'm amused at your inability to understand written communication. I listed reducing casting costs and having type information as SEPARATE benefits. – Mr. TA Dec 12 '17 at 14:12