【问题标题】:.NET XML Serialization and Null Collections.NET XML 序列化和空集合
【发布时间】:2011-01-09 18:08:38
【问题描述】:

我有一个包含一些集合的类,我想将此类的实例序列化为 XML,而不必将集合初始化为空,也不必实现 IXmlSerializable。我不在乎它是创建空元素,还是根本不创建元素。只是它无需为每个基于集合的属性初始化集合即可工作。

我查看了我可以用来装饰属性的所有 XML 属性,但没有成功。这似乎是一件简单的事情,可以有一个元素或根本没有。然后当它被反序列化时,它只会让它们为空或忽略它们。

这是用于解决此问题的类的简单版本。使用这个和默认值,你会得到一个异常“对象引用未设置为对象的实例”,因为集合为空;

public class MyClass
{
    public string Name { get; set; }
    public bool IsAlive { get; set; }
    public List<Car> Cars { get; set; }
    public List<Home> Homes { get; set; }
    public List<Pet> Pets { get; set; }

    public void ToXmlFile(string fileName)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
        TextWriter writer = new StreamWriter(fileName);
        serializer.Serialize(writer, this);
        writer.Close();
    }
}

编辑 感谢您的帮助,事实证明问题出在我的 GetHashCode 方法中,该方法没有正确处理 null。一旦我解决了这一切都很好。我将第一个回答的标记为正确。对不起红鲱鱼,但与你们一起解决它确实有帮助。

【问题讨论】:

  • 还有什么问题?这应该有效(至少序列化和反序列化);你不喜欢什么行为?
  • 我无法重现您声称获得的异常。正如您提供的那样,我能够序列化和反序列化您的确切 MyClass 的实例。也许还有其他事情发生?
  • @Brian 是的,还有其他事情正在发生,感谢所有快速帮助并表明它不是 XML 代码本身。 :)
  • 是什么原因造成的?很好奇,因为我遇到了同样的异常,并且很确定这不是序列化。
  • @rushonerok 正如 2010 年 1 月 27 日帖子中的编辑所述,该问题是一个红鲱鱼,不是由 XmlSerializer 引起的,而是由我对 GetHashCode 的覆盖没有正确考虑 null 引起的。

标签: c# .net serialization collections xml-serialization


【解决方案1】:

您无需初始化集合即可将类序列化为 XML。这是一个简单的程序来演示:

class Program
{
    static void Main(string[] args)
    {
        MyClass c = new MyClass() { Name = "Test", IsAlive = true };
        XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
        using (MemoryStream ms = new MemoryStream())
        {
            serializer.Serialize(ms, c);
            Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
        }
        Console.ReadLine();
    }
}

这将打印以下输出:

<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Test</Name>
  <IsAlive>true</IsAlive>
</MyClass>

换句话说,null 集合属性的行为方式与任何其他 null 属性相同 - 它们根本不会被序列化(除非您更改默认值,我没有)。

【讨论】:

  • 我更新了问题,执行此操作时出现异常“对象引用未设置为对象的实例”。我正在使用 StreamWriter 对文件执行此操作,并从类本身的 ToXmlFile 方法执行此操作,该方法使用“this”关键字来引用要序列化的对象。为通用列表定义的类很简单,其中只有原语或枚举。你说的是我期望它如何工作,但事实并非如此。我也将使用用于序列化的代码更新该类。
  • 谢谢,问题出在其他地方,正如 Brian 在对该问题的评论中所回避的那样。
【解决方案2】:

您可以毫无问题地对其进行序列化,只需在 extraTypes 参数中序列化时发送汽车、家庭和宠物的类型。

【讨论】:

    【解决方案3】:

    您在(反)序列化期间提到了一个异常;您所拥有的应该可以正常工作(至少,根据您定义问题的方式)。我想知道你是否真的有:

    public class MyClass
    {
        public string Name { get; set; }
        public bool IsAlive { get; set; }
        public List<Car> Cars { get; private set; }
        public List<Home> Homes { get; private set; }
        public List<Pet> Pets { get; private set; }
    }
    

    (不想要公共设置器的情况并不罕见)

    好吧,XmlSerializer 对此很挑剔;您要么需要一个公共二传手,要么(正如最近有人指出的那样)no 二传手;例如:

    public class MyClass
    {
        public string Name { get; set; }
        public bool IsAlive { get; set; }
        private readonly List<Car> cars = new List<Car>();
        public List<Car> Cars { get { return cars; } }
        private readonly List<Home> homes = new List<Home>();
        public List<Home> Homes { get { return homes; } }
        private readonly List<Pet> pets = new List<Pet>();
        public List<Pet> Pets { get { return pets; } }
    }
    

    【讨论】:

      【解决方案4】:

      我认为将 XMLSerialisation 方法的返回类型设置为 bool 可以让您以比当前方法更安全的方式处理错误:

      public bool ToXmlFile(string fileName)
      {
          if(fileName != "")
          {
             XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
             TextWriter writer = new StreamWriter(fileName);
             serializer.Serialize(writer, this);
             writer.Close();
             return true;
          }
          return false;
      }
      

      然后可以这样使用:

      if(ToXMLFile)
      {
           MessageBox.Show("Save Succesful");
      }
      else
      (
           MessageBox.Show("Save unsuccesful");
      )
      

      这只是一个粗略的例子,但是我在自己的应用程序中加载或保存数据时使用了类似的方法,并且效果很好,对于最终用户来说也是一个很好的视觉指标。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-31
        • 2012-04-09
        相关资源
        最近更新 更多