【问题标题】:Serialization bugs in .NET?.NET 中的序列化错误?
【发布时间】:2010-09-03 11:30:44
【问题描述】:

我正在阅读有关序列化的内容,到目前为止,我一直在搞乱 BinaryFormatter 和 SoapFormatter。到目前为止,一切都很好 - 一切都完美地序列化和反序列化。

但是,当我尝试下面的代码时,我希望我的数据文件不包含 Name 的信息 - 它确实包含。当我在字段上指定 SoapIgnore 时,它​​为什么会包含它?

我还尝试在年龄字段上使用SoapAttribute("SomeAttribute"),但这也没有任何区别。框架版本设置为 2.0,但同样的事情发生在 3.5 和 4.0。

using System;
using System.Runtime.Serialization.Formatters.Soap;
using System.IO;
using System.Xml.Serialization;

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        p.Age = 42;
        p.Name = "Mr Smith";

        SoapFormatter formatter = new SoapFormatter();
        FileStream fs = new FileStream(@"c:\test\data.txt", FileMode.Create);

        formatter.Serialize(fs, p);
    }
}

[Serializable]
class Person
{
    public int Age;
    [SoapIgnore]
    public string Name;
}

【问题讨论】:

    标签: c# .net serialization soap-serialization


    【解决方案1】:

    使用[NonSerialized] 代替[SoapIgnore]

    此外,这是一个较旧(且老化)的 API。没有直接错误,但请务必阅读XmlSerialization 和ProtoBuf。

    注意不要混淆 API。序列化是 SOAP 通信的一部分,但并不相同。 SoapAttribute 不参与裸序列化。

    【讨论】:

    • 不。不正确。 [NonSerialized] 用于 BinaryFormatter。 [SoapIgnore] 用于 SoapFormatter。 [XmlIgnore] 用于 XmlSerializer。
    • @Peter:你确定吗?来自 MSDN:使用 BinaryFormatter 或 SoapFormatter 类序列化对象时,使用 NonSerializedAttribute 属性 ....,msdn.microsoft.com/en-us/library/…
    • @Peter:根据文档msdn.microsoft.com/en-us/library/… [SoapIgnore] 用于 XMLSerializer,而不是 SoapFormatter
    • 实际上,我也会远离 XML 序列化程序,除非您需要控制 XML 的确切格式。它正在与 ASMX Web 服务一起被删除。
    • 那么我将如何通过 BinaryFormatter、SoapFormatter 或 XmlSerializer 对对象进行序列化,我可以控制哪些字段被序列化?唯一的方法似乎是实现 ISerializable - 这可能是 TAD 矫枉过正。
    【解决方案2】:

    因为序列化和 SOAP 不一样。您已将Name 标记为公共,因此序列化程序将对其进行序列化/反序列化。如果您不希望它出现在序列化中,则应将其保护级别更改为受保护。

    【讨论】:

    • 这不仅仅是在序列化过程中忽略某些字段的方法。
    • 有一个 SoapFormatter 用于序列化数据。我不是在谈论网络服务肥皂信封。 MSDN 它自己声明了以下关于 SoapFormatters 的内容:“以 SOAP 格式序列化和反序列化对象或连接对象的整个图。”
    • @Bart,@Peter Olsen - 我对您的问题和一些回复进行了更多阅读,但我的“答案”不完整或不准确。我很想删除它,但这会剥夺潜在的反对者一个明确而现实的机会。
    【解决方案3】:

    从docs 它声明[SoapIgnore] 属性告诉XMLSerializer 不要序列化这个属性,它没有提到SoapFormatter 所以我认为它不适用于它,即使顾名思义就是这样

    【讨论】:

    • 如果我使用 XmlSerializer,并使用 [SoapIgnore] 属性,它会序列化字段。如果我将属性更改为 [XmlIgnore] 它会正确忽略该字段。这是没有意义的,没有办法告诉序列化程序,一个给定的公共字段不应该被序列化。假设我有字符串 firstname、lastname、fullname,并且 fullname 在 ctor 中设置为 firstname +" "+ lastname。为什么我要序列化全名?但我需要全名才能公开。
    • [NonSerialized] 似乎使 SoapFormatter 忽略该字段。
    【解决方案4】:

    以下代码有效。似乎 SoapFormatter 使用与 BinaryFormatter 相同的属性 - [NonSerialized] 属性。然而,这与我正在阅读的 MS Press 书的内容背道而驰。它列出了 SoapIgnore、SoapAttribute 和其他作为在序列化数据时与 SoapFormatter 一起使用的属性。

    这段代码创建了两个文件,它们都没有名称字段。

    using System;
    using System.Runtime.Serialization.Formatters.Soap;
    using System.IO;
    using System.Xml.Serialization;
    
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
            p.Age = 42;
            p.Name = "Mr Smith";
    
            FormatSoap(p);
            FormatXml(p);
        }
    
        private static void FormatXml(Person p)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Person));
            FileStream fs = new FileStream(@"c:\test\xmldata.txt", FileMode.Create);
    
            serializer.Serialize(fs, p);
        }
    
        private static void FormatSoap(Person p)
        {
            SoapFormatter formatter = new SoapFormatter();
            FileStream fs = new FileStream(@"c:\test\soapdata.txt", FileMode.Create);
    
            formatter.Serialize(fs, p);
        }
    }
    
    [Serializable]
    public class Person
    {
        public int Age;
        [XmlIgnore]
        [NonSerialized]
        public string Name;
    }
    

    【讨论】:

    • 当然,这并不意味着我可以改变我希望生成的soapenvelope 的创建方式——为soap-attributes 设置一些值并重命名其他字段。
    • @Peter:哪本书,什么时候出版的?
    • @John:这是 70-536 考试的自定进度培训工具包(.Net 应用程序开发基金会)。它甚至是 2009 年的第二版。
    • @Peter:顺便说一句,只需阅读代码,就必须对您在 FileStream 周围不使用 using 块表示反对。
    • @John hehe,代码不是生产代码或任何东西——只是为了做一个简单的例子。考试是针对 2.0 的。
    【解决方案5】:

    【讨论】:

    • 该问题的答案指出,SoapIgnore 属性仅适用于 Web 服务。我的问题源于阅读 70-536 的 MS Press 书籍,其中明确指出 SoapIgnore 和 SoapAttribute 与 SoapFormatter 结合使用以序列化对象。
    • 是的,但那些书因错误而臭名昭著。您是否检查过书籍更正页面以查看它是否列出? microsoft.com/learning/en/us/training/…
    猜你喜欢
    • 1970-01-01
    • 2015-06-17
    • 2014-04-09
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 1970-01-01
    相关资源
    最近更新 更多