简体   繁体   English

从基类序列化和反序列化派生类

[英]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. 我试图创建一个基类,可以从中继承(将属性添加到派生类),并利用基类的Load和Save方法。 I find myself writing the Load and Save over and over and I'd like to apply some DRY to it... 我发现自己一遍又一遍地写加载和保存,我想对其应用一些DRY ...

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"); ApplicationParameters参数= 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. 但是,在上述实现中,当我在基类中调用Load方法时,尝试将ApplicationSettings强制转换为ApplicationParameters类时,会发生编译器错误。

Is there a way to do this? 有没有办法做到这一点?

Try replacing typeof(ApplicationSettings) with GetType(). 尝试用GetType()替换typeof(ApplicationSettings)。

Using this mechanism you will also tell the serializer that ApplicationParameters is a child class of ApplicationSettings. 使用这种机制,您还将告诉序列化程序ApplicationParameters是ApplicationSettings的子类。 You do this via XmlInclude 您可以通过XmlInclude执行此操作

[XmlInclude(typeof(ApplicationParameters))]
class ApplicationSettings

The latter is a requirements of the serializer because otherwise it won't know what class to instantiate. 后者是串行器的要求,因为否则它将不知道要实例化哪个类。

Why are you using XmlSerializer ? 为什么使用XmlSerializer?

Unless you must control the way the output XML looks, DataContractSerializer is recommended 除非必须控制输出XML的外观,否则建议使用DataContractSerializer

See here , for example 例如在这里

Make the top level class generic so that the Save/Load methods can support multiple types: 使顶级类通用,以便Save / Load方法可以支持多种类型:

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: 现在,您会注意到,抽象父类的Save / Load方法被强力地键入到子类,因此以下行将按预期工作:

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

or 要么

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

Depending on which method you use. 取决于您使用的方法。

How about a constructor in your ApplicationParameters class that takes an ApplicationSettings as an argument and copy the shared properties from one to another? 您的ApplicationParameters类中的构造函数如何将ApplicationSettings作为参数并将共享属性从一个复制到另一个呢? And then just set the not shared properties to be null or the default... 然后将非共享属性设置为null或默认值...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM