Serialize and DeSerialized derived classes from the base class

大兔子大兔子 提交于 2019-12-11 00:27:47

问题


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?


回答1:


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.




回答2:


Try replacing typeof(ApplicationSettings) with GetType().

Using this mechanism you will also tell the serializer that ApplicationParameters is a child class of ApplicationSettings. You do this via XmlInclude

[XmlInclude(typeof(ApplicationParameters))]
class ApplicationSettings

The latter is a requirements of the serializer because otherwise it won't know what class to instantiate.




回答3:


Why are you using XmlSerializer ?

Unless you must control the way the output XML looks, DataContractSerializer is recommended

See here, for example




回答4:


How about a constructor in your ApplicationParameters class that takes an ApplicationSettings as an argument and copy the shared properties from one to another? And then just set the not shared properties to be null or the default...



来源:https://stackoverflow.com/questions/3959340/serialize-and-deserialized-derived-classes-from-the-base-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!