类应该能够通过 XML 保存和加载自己吗?

Posted

技术标签:

【中文标题】类应该能够通过 XML 保存和加载自己吗?【英文标题】:Should classes be able to save and load themselves via XML? 【发布时间】:2011-08-02 18:55:55 【问题描述】:

所以主要是我在这里寻找最佳实践的答案。我有一个系统,基本上是一组规则、一些数据和一个确保数据遵循规则的管理器。很简单。我试图找出处理保存和加载规则的最佳方法。作为第一次尝试,我有一个名为 IRule 的接口,它继承了所有规则。

interface IRule

  /* all rules inherit this */
  string RuleName get;

interface IRuleTypeA : IRule

  /* Type A Rules */
  double[] Data;


interface IRuleTypeB : IRule

  /* Type B Rules */
  double[,] Data;


public static class IRuleExtensions

  XElement AsXml(this IRuleTypeA ruleA)
  
    //format my data my way and return an XElement representation
    return new XElement(...);
  
  XElement AsXml(this IRuleTypeB ruleB)
  
    //format my different data in a different way and return an XElement
    return new XElement(...);
  
  XElement AsXml(this IRule rule)
  
    object definition = null;
    if(rule is IRuleTypeA)
      definition = (rule as IRuleTypeA).AsXml();
    else if(rule is IRuleTypeB)
      definition = (rule as IRuleTypeB).AsXml();
    return new XElement("RuleDefinition", new XAttribute("name", rule.RuleName),
                         definition);
  

所以在这里,我将保存功能放入正在保存的类中。我即将实现一个类似的加载机制,它将获取每个元素并构造一个规则。在我这样做之前,我想看看是否有这方面的最佳实践。我是否应该创建一个单独的系统来接受规则,询问它,然后将其保存到 XML 并使用工厂类型系统来使用 Xml 来构造对象?

interface RuleToXmlAdaptor

  XElement AsXml(IRule rule);
  IRule FromXml(XElement element);

class RuleAToXmlAdaptor : RuleToXmlAdaptor

  XElement AsXml(IRule rule)  return AsXml(rule as IRuleTypeA); 
  XElement AsXml(IRuleTypeA rule);

我在这些方法之间来回切换,不确定何时使用其中一种,或者是否还有更好的解决方案。

我不想使用序列化,因为文件类型可能会不断变化,而我可以通过这种方式相当简单地管理兼容性。

【问题讨论】:

【参考方案1】:

我认为类本身不应该知道如何序列化它。这违反了单一职责原则。想想明天会出现一种新的令人敬畏的序列化格式的情况,比如 SoupML。如果你让对象之外的人负责序列化,那么让你的系统与 SoupML 一起工作应该很容易,你甚至不必更改现有的规则模型。

理想情况下,只有那些明确使用 XML 的单元才应该知道 XML,这样您的系统可以由不关心格式而只关心接口的单元组成。稍后他们将被告知使用哪个序列化器/反序列化器(控制反转)。采用这种方式也支持开闭原则。您不必撬开东西进行修改,但它会为扩展而打开。

【讨论】:

+1,所有参数都是正确的,甚至可以让您拥有多种序列化格式。此外,您的课程将更简单、更易于理解和改进。 感谢您深思熟虑的答案。你会采用适配器的方法还是像添加 Save(ISave saver) saver.Save(this); 方法到我的规则?【参考方案2】:

我认为您必须开始查看可用于您的类和属性的 xml 属性,这些属性可以让您轻松地将类对象序列化为 xml 文件并在需要时再次反序列化。

【讨论】:

您可以使用 xml 属性管理所有内容,并且可以管理它们在 xml 文件中的外观。【参考方案3】:

我不会这样做,因为它会束缚你的双手,尽管在短期内它可能更方便。而不是XElement,为什么不让接口暴露Dictionary<string,object>。然后,您可以拥有键值对(具有众所周知的值类型,例如 StringDictionary<string,object>)。这样,单元测试会更容易,并且您可以选择使用更有效的格式。

interface RuleSerializer

  Dictionary<string,object> AsDictionary(IRule rule);
  IRule FromDictionary(Dictionary<string,object> data);

【讨论】:

以上是关于类应该能够通过 XML 保存和加载自己吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 C# windows 窗体中制作的保存/加载控件

从保存的文件初始化类

一个类应该在内部处理它自己的数据吗?

将我的变量类保存到 XML 文件

我们可以使用 Sparktrials 保存 Hyperopt 试验的结果吗

从 XML 文件填充文本框