【问题标题】:How should I deserialize this string data?我应该如何反序列化这个字符串数据?
【发布时间】:2009-02-02 17:09:47
【问题描述】:

我的应用程序接收表示对象的字符串。我必须解析字符串以获取我正在创建的对象的属性值。每个对象都必须知道有多少属性、每个属性的含义等细节。但是,我想避免让每个类都知道如何解析字符串。我宁愿为每个单独的对象传递一个更合适的数据结构(如数据集或 XML)......更容易填充其属性的东西。

.NET 框架中是否有适合这种类型的东西?还是我应该创建自己的容器对象?

添加:

我认为我最初对我的问题的解释不够好。这是一个澄清的例子。

假设我的程序总是传递一个字符串,表示 Wiki 语法中的数据表。比如:

  {||Client:||ABC|-|Contact:||Joe Smith|-|Current revision:||1.0||}

我不希望我的每个特定 wiki 表对象(例如,ClientContactTable、CustomerOrderTable 等)都知道如何解析 |和 - 和}。因此,我想编写 1 块代码,将字符串解析为一些“中间”层对象,我可以将其传递给每个特定 Wiki 表对象的构造函数。

我的问题是:中间层对象应该是什么?

【问题讨论】:

    标签: .net parsing serialization data-structures


    【解决方案1】:

    我可能对您的问题理解有误,但我认为标准 .NET 序列化符合您的需求:

    var ms = new MemoryStream();
    var formatter = new BinaryFormatter();
    formatter.Serialize(ms, myObject);
    
    // Deserialization:
    var deserialized = (MyClass)formatter.Deserialize(stream);
    

    【讨论】:

    • 对象中的 List 属性是什么?
    【解决方案2】:

    【讨论】:

    • 这看起来是正确的做法。您真的不希望将字符串转换为某种 XML 表示然后必须从中反序列化它的性能开销。
    【解决方案3】:

    一种传统的方法是通过System.Xml.Serialization 类。这允许您将对象序列化到磁盘,并在以后反序列化它们。这有一些限制:类型应该是公共的,有一个公共的无参数构造函数,并且有 XmlSerializer 属性。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Xml.Serialization;
    
    
    namespace ConsoleApplication1
    {
        [Serializable]
        public class Cat
        {
            DateTime _dateOfBirth;
            string _name;
    
            public DateTime DateOfBirth
            {
                get { return _dateOfBirth; }
                set { _dateOfBirth = value; }
            }
    
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
    
            public Cat() : this(DateTime.Now, "(Cat with no name)") { }
    
            public Cat(DateTime dateOfBirth, string name)
            {
                this.DateOfBirth = dateOfBirth;
                this.Name = name;
            }
    
            public override string ToString()
            {
                return string.Format("Name: {0}, DateOfBirth: {1}", Name, DateOfBirth);
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Cat originalCat = new Cat(DateTime.Now, "Fluffy");
                XmlSerializer serializer = new XmlSerializer(typeof(Cat));
    
                MemoryStream memStream = new MemoryStream(); // can be file stream
                serializer.Serialize(memStream, originalCat);
    
                memStream.Position = 0; // this is just here to make this code sample work, usually you
                                        // you don't need to set your streams position manually
    
                Cat deserializedCat = (Cat)serializer.Deserialize(memStream);
    
                Console.WriteLine("originalCat.ToString(): {0}", originalCat.ToString());
                Console.WriteLine("deserializedCat.ToString(): {0}", deserializedCat.ToString());
    
                Console.ReadKey(true);
            }
        }
    }
    

    一般来说,您应该非常小心处理这种序列化。当您尝试在同一程序集的不同版本之间序列化/反序列化对象时,就会发生奇怪的事情。

    编辑添加:上面的代码会将您的对象序列化为 XML。您可以通过将 MemoryString 替换为 StringWriter 来查看 XML 表示形式(调用 stringWriterInstance.ToString() 方法直接获取 XML 字符串)。其他人建议使用 BinaryFormatter,它或多或少做同样的事情,但输出是二进制而不是文本。

    这两种方法都是序列化数据的有效方法,这取决于您更喜欢处理 XML 数据还是二进制数据。

    【讨论】:

      【解决方案4】:

      您需要解析字符串数据并将其转换为对象或 xml - 我建议您使用 string.split 创建一个集合(数组),然后使用 linq 创建您想要的数据结构并传递给工厂根据您传递给工厂的参数以及数据结构返回正确的对象。

      【讨论】:

        【解决方案5】:

        如果您需要存储您的对象,您应该使用 XmlSerializer(s)。 这会将您的对象反序列化为 XML 并为您解析它们。

        public List<_type> LoadDataFromResource<_type>(string file)
        {
           List<_type> data = new List<_type>();
           FileStream str = File.OpenRead(file);
           if (str == null) return null;
           XmlSerializer sr = new XmlSerializer(data.GetType());
           if (sr == null) return null;
           data = sr.Deserialize(str) as List<_type>;
           return data;
        }
        
        public bool SaveData<_type>(string file, List<_type> data)
        {
        StreamWriter writer = File.CreateText(file);
        if (writer == null) return false;
        XmlSerializer sr = new XmlSerializer(data.GetType());
        if (sr == null) return false;
        sr.Serialize(writer, data);
        return true;
        }
        

        【讨论】:

          猜你喜欢
          • 2014-02-14
          • 1970-01-01
          • 2012-02-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-22
          • 1970-01-01
          相关资源
          最近更新 更多