Search code examples
c#xml-serialization.net-2.0

Serialize and DeSerialized derived classes from the base class


I am trying to create a base class where I can inherit from it (to add properties to the derived classes) and the utilized the Load and Save methods from the base class. I find myself writing the Load and Save over and over and I'd like to apply some DRY to it...

namespace Common

{
  using System;
  using System.IO;
  using System.Xml.Serialization;

  public abstract class ApplicationSettings
  {
    protected ApplicationSettings()
    {
    }

    public static ApplicationSettings Load(string fileName)
    {
      if (!File.Exists(fileName))
      {
        return null;
      }

      XmlSerializer serializer = new XmlSerializer(typeof(ApplicationSettings));

      using (StreamReader reader = new StreamReader(fileName))
      {
        ApplicationSettings param = (ApplicationSettings)serializer.Deserialize(reader);
        reader.Close();
        return param;
      }
    }

    public void Save(string fileName)
    {
      XmlSerializer serializer = new XmlSerializer(typeof(ApplicationSettings));
      using (StreamWriter writer = new StreamWriter(fileName))
      {
        serializer.Serialize(writer, this);
        writer.Close();
      }
    }
  }
}

Given this abstract class, I then want to derive a class such as:

namespace Common
{
  using System;

  public class ApplicationParameters : ApplicationSettings
  {
    public ApplicationParameters()
    {
    }
    public string AuthorizationCode
    {
      get;
      set;
    }
    public string ReferenceNumber
    {
      get;
      set;
    }
  }
}

For the Derived class, I should be able to do something like

ApplicationParameters parameters = ApplicationParmeters.Load("settings.xml");

However, in the implementation above, an compiler error occurs when I attempt to cast the ApplicationSettings to the ApplicationParameters class when I call the Load method in the base class.

Is there a way to do this?


Solution

  • Make the top level class generic so that the Save/Load methods can support multiple types:

    public abstract class ApplicationSettings<T>
    {
        public static T Load(string xml){ // Implementation }
    
        public static void Save (T obj) { // Implementation }
    }
    
    public class ApplicationParameters : ApplicationSettings<ApplicationParameters>
    {
    }
    

    Or you could just make the static methods themselves generic:

    public abstract class ApplicationSettings
    {
        public static T Load<T>(string xml){ // implementation }
    
        public static void Save<T>(T obj){ // implementation }
    }
    

    You will now notice that the Save/Load methods from the abstract parent class are strongly typed to the child so that the following line will work as expected:

    ApplicationParameters parameters = ApplicationParameters.Load("settings.xml");
    

    or

    ApplicationParameters parameters =
        ApplicationSettings.Load<ApplicationParameters>("settings.xml");
    

    Depending on which method you use.