【问题标题】:How to serialize/deserialize simple classes to XML and back如何将简单的类序列化/反序列化为 XML 并返回
【发布时间】:2011-03-22 09:09:45
【问题描述】:

有时我想模拟我的类的存储数据,而不需要设置到数据库的往返行程。例如,假设我有以下类:

public class ShoppingCart
{
    public List<CartItem> Items {get; set;}
    public int UserID { get; set; }
}

public class CartItem
{
    public int SkuID { get; set; }
    public int Quantity  { get; set; }
    public double ExtendedCost  { get; set; }
}

假设我在内存中构建了一个ShoppingCart 对象并希望将其“保存”为 XML 文档。这可以通过某种XDocument.CreateFromPOCO(shoppingCart) 方法实现吗?在另一个方向上怎么样:有没有一种内置的方法可以从像 new ShoppingCart(xDoc) 这样的 XML 文档创建一个 ShoppingCart 对象?

【问题讨论】:

    标签: c# .net xml poco


    【解决方案1】:

    XmlSerializer 是一种方法。 DataContractSerializer 是另一个。以XmlSerializer 为例:

    using System.Xml;
    using System.Xml.Serialization;
    
    //...
    
    ShoppingCart shoppingCart = FetchShoppingCartFromSomewhere();
    var serializer = new XmlSerializer(shoppingCart.GetType());
    using (var writer = XmlWriter.Create("shoppingcart.xml"))
    {
        serializer.Serialize(writer, shoppingCart);
    }
    

    并将其反序列化:

    var serializer = new XmlSerializer(typeof(ShoppingCart));
    using (var reader = XmlReader.Create("shoppingcart.xml"))
    {
        var shoppingCart = (ShoppingCart)serializer.Deserialize(reader);
    }
    

    另外,为了更好地封装,我建议您在 CartItem 类中使用属​​性而不是字段。

    【讨论】:

    • 感谢您的建议。我本来打算使用属性而不是字段。固定。
    • 我花了一些时间来测试它,但它运行良好。谢谢!
    • 我希望我能在过去几周内每次导航到这个答案时给你一个赞成票。它一直在派发股息!
    【解决方案2】:

    做得很好。这是将普通 POCO 序列化为字符串的示例。

        private string poco2Xml(object obj)
        {
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            StringBuilder result = new StringBuilder();
            using (var writer = XmlWriter.Create(result))
            {
                serializer.Serialize(writer, obj);
            }
            return result.ToString();
        }
    

    【讨论】:

      【解决方案3】:

      您可以使用XmlSerializerDataContractSerializer 进行序列化/反序列化。

      使用 DataContractDataMember 属性注释您的类,并编写类似这样的内容以将 xml 序列化为文件。

      ShoppingCart cart = ...
      using(FileStream writer = new FileStream(fileName, FileMode.Create))
      {
         DataContractSerializer ser = new DataContractSerializer(typeof(ShoppingCart));
         ser.WriteObject(writer, cart);
      }
      

      【讨论】:

      • 序列化过程中抛出异常怎么办?
      • @Darin:在开始使用 DataContractSerializer 时经常会遇到这种情况。但它通常归结为类的属性注释。 XmlSerializer 更易于使用,因为它几乎可以接受任何你扔给它的东西,但 DataContractSerializer 更快,但需要更多的“工作”才能启动和运行。
      • @Mikael,我想你没有明白我的意思。我的意思是,如果抛出异常,您将泄漏一个非常糟糕的文件句柄,因为它会锁定文件,并且在您终止应用程序之前没有其他进程能够对它做任何事情。
      • @Mikael,StackOverflow 是一个被广泛引用的网站,这意味着您在此处编写的内容可能会被许多人在生产代码中看到和不负责任地使用,我认为像处理一次性资源这样的基本事情是最低限度的以避免推广不良做法。我敢肯定,有很多人只是简单地从博客文章中复制粘贴,甚至没有意识到这可能对他们的生产系统产生灾难性影响。
      • @Darin:确实如此。实际上,我从 MSDN 复制/粘贴了我的代码并对其进行了修改,因此他们在示例中也有工作要做。除了示例是控制台应用程序,因此任何文件锁定都将在程序“崩溃”时处理。
      【解决方案4】:

      只需使用 [XmlElement(name)](或 XmlAttribute、XmlRoot 等)标记您要序列化的内容,然后使用 XmlSerializer。如果您确实需要自定义格式,请实现 IXmlSerializable。

      【讨论】:

      • 为什么不像线程上的其他答案一样提供代码示例?
      猜你喜欢
      • 2014-01-20
      • 2010-12-27
      • 1970-01-01
      • 2022-01-02
      • 2020-07-10
      • 1970-01-01
      • 2016-06-07
      • 1970-01-01
      • 2021-12-12
      相关资源
      最近更新 更多