代码之家  ›  专栏  ›  技术社区  ›  Dave

很难决定.NET中可用的XML序列化选项

  •  2
  • Dave  · 技术社区  · 14 年前

    直到昨晚,我一直在使用.NET中的各种库分析XML-- XmlDocument XDocument 主要是。我不知道为什么我没有早点研究这个问题,但我突然想到.NET中一定有一些东西可以免费为您提供类序列化/反序列化,当然它是以 XmlSerializer 班级。

    当然,通过使用几行代码,我可以轻松地进行序列化和反序列化(尽管在我目前正在编写的代码中, 只需要反序列化 ,并且不再需要花费几个小时左右的时间来编写我自己的类来与其他库一起完成这项工作,再加上必要的单元测试。但问题是我希望我的属性是只读的。如果我将setter设为私有,那么在创建xmlserializer时,我会得到以下错误:

    无法生成临时类(结果=1)。 错误CS0200:无法将属性或索引器“MyProperty”分配给--它是只读的

    看起来像 this is an issue that won't be resolved 所以必须有一个解决办法。

    当然,我发现 this information ,这表示如果放弃自动属性并返回私有字段,则可以获取要编译的代码。不幸的是,虽然这会编译,但在执行代码时,它实际上不会反序列化数据。停止应用程序后,我注意到“消息”窗口中有几个条目说:

    找不到元素“MyProperty”的架构信息。

    这是因为没有代码可以为MyProperty赋值,因为XmlSerializer不知道如何处理私有字段!!!!

    我在StackOverflow上找到了一个答案 another solution ,即使用 DataContractSerializer 我以前没听说过。我对我的课程做了必要的代码更改,但最终得到了与上面相同的消息。我运行代码来确定,当XML被反序列化时,类成员不会被设置。

    我在想,在我的特殊情况下,我要么接受它,允许成员被覆盖(坏),要么我回到我最初的工作方式,即自己编写所有的序列化/反序列化代码。这里是否有我做错的地方,或者不可能允许像xmlserializer这样的类在反序列化期间设置类的私有成员,同时使类的使用者无法覆盖其成员?

    更新 还有 yet another article 这显示了另一种对私有属性进行反序列化的方法,但我刚尝试过,但它也不起作用。

    下面是我试图反序列化的类的一些示例:

    [Export]
    [DataContract]
    public class Configuration
    {
        [DataMember(Name="Port")]
        private int _port;
        public int Port { get { return _port; }}
    }
    

    结果:使用XmlSerializer反序列化时,没有错误,但当我的XML文件的端口值为1时,端口和端口的值为0,例如。 <Port>1</Port> .

    另一个例子:

    [Export]
    public class Configuration
    {
        public int Port { get; set; }
    }
    

    结果:反序列化很好,但我不需要公共setter。

    我将类反序列化如下:

    XmlSerializer serializer = new XmlSerializer(typeof(Configuration));
    FileStream reader = new FileStream( "config.xml", FileMode.Open);
    Configuration Config = (Configuration)serializer.Deserialize( reader);
    reader.Close();
    
    3 回复  |  直到 14 年前
        1
  •  3
  •   Steven Sudit    14 年前

    我没有一个好答案,但我有几个坏答案。无特殊顺序:

    1. 您可以创建一个具有r/w属性的纯数据传输对象,并将其用于序列化/反序列化。然后,您可以通过用DTO构造来初始化不可变的业务对象。

    2. 您提到的两个序列化程序类还允许通过属性和代码的组合来重写它们的行为。这可能足以解决您的问题,但可能比它的价值更大。

        2
  •  1
  •   Jon Hanna    14 年前

    这不是要使用哪个XML序列化方法的问题,而是关于序列化本身的问题(尝试使用二进制序列化,您将得到相同的错误)。

    如果无法更改属性以允许执行默认的序列化方法,则:

    1. 实现ISerializable接口。
    2. 在getObjectData实现中,将值添加到为需要记录的每个字段传递的SerializationInfo参数中。
    3. 添加一个采用SerializationInfo参数和StreamingContext参数的构造函数(它不必是公共的)。在此构造函数中,可以从序列化期间写入的序列化信息中读取数据,从而生成反序列化对象。

    现在,这看起来有点像回到手工序列化,但是它只需要在Quesiton中的类上进行,而且它还可以通过其他机制使类序列化。

        3
  •  0
  •   Dave    14 年前

    我认为,最终,这个问题的正确答案是,如果需要反序列化(序列化不是问题)私有数据,那么您希望避免使用XmlSerializer和DataContractSerializer。我仍然希望我是错的,但最后,乔恩可能是对的——我要么使用ISerializable,要么用我到现在为止一直在做的方式来做。

    今晚,当我决定使用一个具有公共属性的类来允许反序列化,然后用另一个类包装它时,我碰到了另一个砖墙。我不想将反序列化类公开——我希望它是只公开只读属性的类中的私有类。问题是,xmlserializable不能处理私有类。

    我可以暂时公开这个班,我可以先把事情做好,但我要走另一条路,因为公开这个班是没有意义的。