Saturday, May 11, 2013

XmlSerializer - Difference in runtime behaviour between MS .Net and Mono runtime

There are several ways to define a class in C# with read-only properties.

You could define it like this:
    [ Serializable ]
    public class PersonReadOnly
    {
        String m_Name;
        Int32 m_Age;
        public String Name {
            get{ return m_Name; }
        }
        public Int32 Age { 
            get{ return m_Age; }
        }

        public PersonReadOnly()
        {
        }

        public PersonReadOnly (String name, Int32 age)
        {
            this.m_Name = name;
            this.m_Age = age;
        }
    }

This is the good old way of doing it. When this class is serialized using Xml Serialization, the values of the properties are not serialized.

Alternately, you can declare one with a private setter or using the auto-generated property syntax with private setter, like this:
    [ Serializable ]
    public class WithAutoPropertyReadOnly
    {
        public String Name { get; private set; }
        public Int32 Age { get; private set; }

        public WithAutoPropertyReadOnly() { }

        public WithAutoPropertyReadOnly( string name, Int32 age )
        {
            this.Name = name;
            this.Age = age;
        }
    }

The end result of this class WithAutoPropertyReadOnly is to produce private setters for properties Name and Age.

While WithAutoPropertiesReadOnly and PersonReadOnly classes are functionally the same, the runtime treatments in CLR (MS .Net) and Mono runtime are very different.

CLR and Mono differences
The Mono runtime used in this experiment is version 2.10.8.1 hosted in Ubuntu 12.04 LTS).

When one tries to construct an XmlSerializer object for the class WithAutoPropertiesReadOnly class, like this:
       XmlSerializer ser = new XmlSerializer( typeof(WithAutoPropertiesReadOnly) ); 

CLR runtime throws an exception of type InvalidOperationException while Mono blissfully serializes and deserializes with XmlSerializer in defiant of the specification.

This is dangerous as it introduces runtime differences that can affect cross-platform compatibility. Irrespective if the above piece of code is run in CLR or Mono, the same runtime behaviour should result.

This anomaly between CLR (runtime 2.0 & 4.0) and Mono only manifested by the presence of non-public property setter. In fact, the exception thrown in CLR is due to the runtime exception thrown by sgen.exe when the runtime tries to generate the temporary serialization DLL.

There is no disagreement when trying to serialize the class PersonReadOnly; both CLR and Mono yield the same result that the values for the properties are not serialized in Xml Serialization.






No comments:

Post a Comment