Re: XML deserialisation - backwards compatability

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Marc Gravell

    #1

    Re: XML deserialisation - backwards compatability

    Maybe not straightforward , but: if you add a hidden Area property, and
    tell it never to serialize, it should work.
    Note I've used C# 3 auto-implemented properties for Width/Height -
    just replace with standard properties if you are using C# 2; but don't
    use public fields... pretty much "ever".

    Marc

    using System;
    using System.Componen tModel;
    using System.IO;
    using System.Xml.Seri alization;

    [Serializable]
    public sealed class MyClass
    {
    public int Width { get; set; }
    public int Height { get; set; }

    [EditorBrowsable (EditorBrowsabl eState.Never), Browsable(false )]
    public int Area
    {
    get { return Width * Height; }
    set { Width = Height = (int)Math.Sqrt( value); }
    }
    [EditorBrowsable (EditorBrowsabl eState.Never), Browsable(false )]
    public bool ShouldSerialize Area() { return false; }

    public override string ToString()
    {
    return string.Format(" {0}x{1}", Width, Height);
    }
    }

    static class Program
    {
    static void Main(string[] args)
    {
    XmlSerializer xs = new XmlSerializer(t ypeof(MyClass)) ;
    MyClass item = new MyClass { Width = 3, Height = 5 };

    StringWriter writer = new StringWriter();
    xs.Serialize(wr iter, item);
    string xml = writer.ToString ();

    Console.WriteLi ne(xml);

    using (StringReader sr = new StringReader(@" <MyClass><Area> 25</
    Area></MyClass>"))
    {
    MyClass oldStyle = (MyClass)xs.Des erialize(sr);
    Console.WriteLi ne(oldStyle);
    }
    using (StringReader sr = new StringReader(@" <MyClass><Width >7</
    Width><Height>3 </Height></MyClass>"))
    {
    MyClass newStyle = (MyClass)xs.Des erialize(sr);
    Console.WriteLi ne(newStyle);
    }
    }
    }
  • Dylan Nicholson

    #2
    Re: XML deserialisation - backwards compatability

    On Apr 11, 4:53 pm, Marc Gravell <marc.grav...@g mail.comwrote:
    Maybe not straightforward , but: if you add a hidden Area property, and
    tell it never to serialize, it should work.
    Note I've used C# 3 auto-implemented properties for Width/Height -
    just replace with standard properties if you are using C# 2; but don't
    use public fields... pretty much "ever".
    >
    Marc
    >
    Thanks...I didn't know about the ShouldSerialize ...() trick - that
    solved the problem of the deprecated field being written to new files.
    But ideally I don't want the deprecated field to be public either.
    Not a biggie, though.
    As for public fields - in this case the class is just a holder for
    fairly raw data, where no particular validation is needed.
    And the beauty of C# is you can change public fields to properties at
    any point and existing code will continue to compile.

    Comment

    • Marc Gravell

      #3
      Re: XML deserialisation - backwards compatability

      But ideally I don't want the deprecated field to be public either.

      Well, it is pretty well hidden by the two attributes - but ultimately
      XmlSerializer works on public properties. If you have .NET 3.0,
      another option is DataContractSer ializer (shown below), since this can
      serialize private members; and a third option is custom serialization
      (IXmlSerializab le), but this is considerably more work.
      As for public fields - in this case the class is just a holder for
      fairly raw data, where no particular validation is needed.
      Then in VS2008 / C# 3, auto implemented properties are definitely the
      way to go.
      And the beauty of C# is you can change public fields to properties at
      any point and existing code will continue to compile.
      That isn't entirely true... first: it forces you to rebuild everything
      that references it, and second: there are cases when this simply isn't
      true; two obvious examples come to mind (there are others):

      * using the field as a "ref" or "out" parameter to a method [can't use
      properties as "ref" or "out"]
      * if the field represents a mutable struct [which you shouldn't have
      anyway], and you are changing nested properties [change gets discarded
      with a property]

      It will almost certainly break binary serialization, too.

      Marc

      ## DataContract example ##

      using System;
      using System.IO;
      using System.Runtime. Serialization;
      using System.Xml;

      [DataContract(Na mespace="")]
      public sealed class MyClass
      {
      [DataMember(IsRe quired = false)]
      public int Width { get; set; }
      [DataMember(IsRe quired=false)]
      public int Height { get; set; }

      [DataMember(Name ="Area", IsRequired=fals e,
      EmitDefaultValu e=false)]
      private int? AreaFacade
      {
      get { return null; }
      set {
      if (value.HasValue )
      {
      Width = Height = (int)Math.Sqrt( value.Value);
      }
      }
      }

      public override string ToString()
      {
      return string.Format(" {0}x{1}", Width, Height);
      }
      }

      static class Program
      {
      static void Main(string[] args)
      {
      DataContractSer ializer xs = new
      DataContractSer ializer(typeof( MyClass));
      MyClass item = new MyClass { Width = 3, Height = 5 };

      StringWriter writer = new StringWriter();
      using (XmlWriter xw = XmlWriter.Creat e(writer))
      {
      xs.WriteObject( xw, item);
      xw.Close();
      }
      string xml = writer.ToString ();

      Console.WriteLi ne(xml);

      using (XmlReader xr = XmlReader.Creat e(new
      StringReader(@" <MyClass><Area> 25</Area></MyClass>")))
      {
      MyClass oldStyle = (MyClass)xs.Rea dObject(xr);
      Console.WriteLi ne(oldStyle);
      }
      using (XmlReader xr = XmlReader.Creat e(new
      StringReader(@" <MyClass><Heigh t>3</Height><Width>7 </Width></
      MyClass>")))
      {
      MyClass newStyle = (MyClass)xs.Rea dObject(xr);
      Console.WriteLi ne(newStyle);
      }
      }
      }

      Comment

      Working...