Answered How to derive from base implementing IXmlSerializable?

  • Tuesday, May 22, 2012 7:52 AM
     
      Has Code

    Hello,

    I am stuck trying to derive from a base class implementing IXmlSerializable. Marking a property in the subclass with [XmlElement] does not serialize the property. What I want is a base class implementing IXmlSerializable for custom serialization but when derived from it should work as an "ordinary class".

    The problem probably lies in my implementation of [XmlSchemaProvider] or maybe what i want to do is not doable?

    I have isolated the code to the following:

        [XmlSchemaProvider("GetXmlSchemaType")]
        public class BaseClass: IXmlSerializable
        {
            public string BaseName { get; set; }
            // This is the method named by the XmlSchemaProviderAttribute applied to the type.
            public static XmlSchemaType GetXmlSchemaType(XmlSchemaSet xs)
            {
                // This method is called by the framework to get the schema for this type.
                // We return an existing schema from disk.
                if(xs.Count!=0)
                {
                    throw new NotImplementedException();
                    //XmlSerializer schemaSerializer = new XmlSerializer(typeof(XmlSchema));
                    //string xsdPath = null;
                    //// NOTE: replace the string with your own path.
                    //xsdPath = System.Web.HttpContext.Current.Server.MapPath("SongStream.xsd");
                    //XmlSchema s = (XmlSchema)schemaSerializer.Deserialize(new XmlTextReader(xsdPath), null);
                    //xs.XmlResolver = new XmlUrlResolver();
                    //xs.Add(s);
                }
                return new XmlSchemaType();
            }
    
            public XmlSchema GetSchema()
            {
                throw new NotImplementedException();
            }
    
            private const string BaseElementName = "BaseName";
    
            public void ReadXml(XmlReader reader)
            {
                this.BaseName = reader.ReadElementString(BaseElementName);
            }
    
            public void WriteXml(XmlWriter writer)
            {
                writer.WriteElementString(BaseElementName,BaseName);
            }
        }

        public class DerivedClass : BaseClass
        {
            [XmlElement]
            public string DerivedName { get; set; }
        }
        [TestFixture]
        public class XmlSerializableTest
        {
            [Test]
            public void SerializeBaseClassTest()
            {
                var baseClass = new BaseClass() {BaseName = "mr Base"};
                var actual = SerializeToString(baseClass);
                Assert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-16""?><BaseClass><BaseName>mr Base</BaseName></BaseClass>", actual);
            }
    
            [Test]
            public void SerializeDerivedClassTest()
            {
                var derivedClass = new DerivedClass() { BaseName = "mr Base",DerivedName = "mr Derived"};
                var actual = SerializeToString(derivedClass);
                Assert.AreNotEqual(@"<?xml version=""1.0"" encoding=""utf-16""?><DerivedClass><BaseName>mr Base</BaseName></DerivedClass>", actual);
            }
    
            private static string SerializeToString<T>(T item)
            {
                var xmlSerializer = new XmlSerializer(item.GetType());
                using (var stringWriter = new StringWriter())
                {
                    using (var xmlTextWriter = new XmlTextWriter(stringWriter))
                    {
                        xmlSerializer.Serialize(xmlTextWriter, item);
                        var xml = stringWriter.ToString();
                        return xml;
                    }
                }
            }
        }



    Trying to learn

All Replies

  • Thursday, May 24, 2012 2:17 AM
    Moderator
     
     

    Hi Johan20D,

    Welcome to MSDN Forum.

    I will do more research on this issue and come back as soon as possible, thanks for your understanding. :)

    Best Reagards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

  • Thursday, May 24, 2012 7:57 AM
    Moderator
     
     Answered

    Hi Johan20D,

    Based on the code, you have implement IXmlSerializable interface in the base class, in the WriteXML method implementation, the write can only been specified how to write BaseName property, but it doesn't know anything about your derived class's properties. So, the 'DerivedName' will not be serialized.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

  • Friday, May 25, 2012 9:06 AM
     
     

    Yes I agree with you that far. My question really is if there is a way to implement IXmlSerializable in the base class such that the base class knows how to serialize its properties and be able to derive from the base class and use attributes to mark how to serialize the derived properties in the standard way. If I make vanilla classes without IXmlSerializable this works fine.

    One solution could be to make ReadXml/WriteXml virtual and override them but it is not very pretty.


    Trying to learn

  • Friday, May 25, 2012 9:21 AM
    Moderator
     
     Answered

    Hi Johan20D,

    Letting the ReadXml and WriteXml method as virtual is the only way. The base class implement IXmlSerializable interface, then XML Tag will not work. Overriding the methods is a good way for this issue. Commonly, we often implement the interface in every class we want to serialize.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us


  • Monday, May 28, 2012 5:06 AM
    Moderator
     
     

    Hi johan20D,

    Any update about this issue? If you neef further help, please feel free to let me know, I will be more than happy to be of assistance. :)

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

  • Monday, June 04, 2012 1:04 PM
     
     

    Letting the ReadXml and WriteXml method as virtual is the only way. The base class implement IXmlSerializable interface, then XML Tag will not work. Overriding the methods is a good way for this issue. Commonly, we often implement the interface in every class we want to serialize.

    If overriding ReadXml and WriteXml it is the only way then I guess that is the answer.


    Trying to learn