【问题标题】:What's up with the [OptionalField] Attribute?[OptionalField] 属性是怎么回事?
【发布时间】:2010-10-30 02:55:31
【问题描述】:

据我了解,当我反序列化缺少此新成员的旧版本类时,我必须使用 [OptionalField] 属性在我的类的新版本中装饰一个新成员。

但是,在序列化类之后添加 InnerTranslator 属性时,下面的代码不会引发异常。我在 onDeserialization 方法中检查该属性是否为空(这确认它没有被序列化),但我本以为代码会因此引发异常。 [OptionalField] 属性本身是可选的吗?

class Program
{
    static void Main(string[] args)
    {
        var listcol = new SortedList<string,string>
        {
            {"Estados Unidos", "United States"},
            {"Canadá", "Canada"},
            {"España", "Spain"}
        };
        var translator = new CountryTranslator(listcol);
        using (var file_stream=new FileStream("translator.bin",FileMode.Open))
        {
            var formatter = new BinaryFormatter();
            translator = formatter.Deserialize(file_stream) as CountryTranslator;
            file_stream.Close();
        }
        Console.ReadLine();
    }
}

[Serializable]
internal class CountryTranslator:IDeserializationCallback
{
    public int Count { get; set; }

    public CountryTranslator(SortedList<string,string> sorted_list)
    {
        this.country_list = sorted_list;
        inner_translator = new List<string> {"one", "two"};
    }
    //[OptionalField]
    private List<string> inner_translator;
    public List<string> InnerTranslator
    {
        get { return inner_translator; }
        set { inner_translator = value; }
    }

    private SortedList<string, string> country_list;

    public void OnDeserialization(object sender)
    {
        Debug.Assert(inner_translator == null);
        Count=country_list.Count;
    }
}

【问题讨论】:

  • 我刚刚发现,当 inner_translator 没有使用 [OptionalField] 属性修饰时,SOAP 格式化程序确实会抛出异常

标签: c# .net serialization fault-tolerance


【解决方案1】:

BinaryFormatter最好的时候,如果你改变一些东西,它会非常脆弱。尤其是automatically implemented properties, obfuscaction、重命名、强命名等存在巨大问题。

我记得,关于[OptionalField] 的一些规则在它发布之前就发生了变化;我预计,版本容忍的事情并没有像计划的那么容易。

我的建议:如果你想要版本容忍的序列化(即你可以在今天序列化它并在你的应用程序的下一个版本中反序列化它),那么不要使用BinaryFormatter;这(IMO)仅适用于在相同版本(远程处理、AppDomains 等)之间传递数据。

对于版本之间的工作,我推荐基于契约的序列化; XmlSerializerDataContractSerializer (.NET 3.0) 之类的东西,或二进制文件 - protobuf-net 或类似工具。所有这些在版本容错方面都好多了(实际上,您甚至不需要将其反序列化为相同的Type);此外,它们可以在平台之间使用 - 因此您可以在 .NET 中序列化并在 java/C++/etc 中反序列化。

【讨论】:

  • 不完全是我正在寻找的答案,但我发现我已经转而专门使用 DataContractSerializer,因为您在这篇文章中提出了它。所以毕竟谢谢;-)
  • 您是否曾经将 [OptionalField] 用于布尔值或整数等值类型?还是此属性仅与 OP 问题中的引用类型相关?
猜你喜欢
  • 2010-11-02
  • 1970-01-01
  • 2011-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
  • 2013-07-06
  • 2012-03-09
相关资源
最近更新 更多