C# 什么';[OptionalField]属性怎么了?

C# 什么';[OptionalField]属性怎么了?,c#,.net,serialization,fault-tolerance,C#,.net,Serialization,Fault Tolerance,据我所知,当我反序列化缺少新成员的类的旧版本时,我必须使用[OptionalField]属性在类的新版本中修饰新成员 但是,在序列化类后添加InnerTranslator属性时,下面的代码不会引发异常。我在onDeserialization方法中检查属性是否为null(这确认了它没有被序列化),但我希望代码会因此引发异常。 [OptionalField]属性本身是可选的吗 class Program { static void Main(string[] args) {

据我所知,当我反序列化缺少新成员的类的旧版本时,我必须使用[OptionalField]属性在类的新版本中修饰新成员

但是,在序列化类后添加InnerTranslator属性时,下面的代码不会引发异常。我在onDeserialization方法中检查属性是否为null(这确认了它没有被序列化),但我希望代码会因此引发异常。 [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;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var listcol=新分类列表
{
{“美国”},
{“加拿大”、“加拿大”},
{“西班牙”}
};
var translator=新的CountryTranslator(listcol);
使用(var file_stream=newfilestream(“translator.bin”,FileMode.Open))
{
var formatter=新的二进制格式化程序();
translator=格式化程序。反序列化(文件流)为CountryTranslator;
文件_stream.Close();
}
Console.ReadLine();
}
}
[可序列化]
内部类CountryTranslator:IDeserializationCallback
{
公共整数计数{get;set;}
公共国家翻译(分类列表分类列表)
{
this.country\u list=已排序的\u list;
内部翻译=新列表{“一”、“二”};
}
//[可选字段]
私有列表内部_转换器;
公共列表内部翻译器
{
获取{return internal_translator;}
设置{internal_translator=value;}
}
私人分类列表国家/地区列表;
公共序列化(对象发送方)
{
Assert(内部_转换器==null);
Count=国家/地区列表。Count;
}
}

二进制格式化程序
在最好的情况下,如果您更改内容,它会非常脆弱。不仅如此,还有很多问题需要解决,例如,命名、重命名、强命名等

我记得,关于
[OptionalField]
的一些规则在发布之前发生了变化;我想,容忍版本的事情并不像计划的那样容易

我的建议:如果您想要版本容忍序列化(即,您可以今天对其进行序列化,并使用下一版本的应用程序对其进行反序列化),则不要使用
BinaryFormatter
;这(IMO)仅适用于在相同版本(远程处理、
AppDomain
s等)之间传递数据


对于版本之间的工作,我建议基于契约的序列化;类似于
XmlSerializer
DataContractSerializer
(.NET3.0),或者针对二进制或类似工具。所有这些在版本容忍度方面都要好得多(实际上,您甚至不需要将其反序列化为相同的
类型
);另外,它们可以在平台之间使用-因此您可以在.NET中序列化,并在java/C++/等中反序列化。

我刚刚发现,当内部转换器没有使用[OptionalField]属性装饰时,SOAP格式化程序确实会引发异常。这与我所寻找的答案不完全相同,但是我发现自从你在这篇文章中建议使用DataContractSerializer之后,我已经转而专门使用DataContractSerializer。所以还是谢谢你;-)您是否会将[OptionalField]用于布尔或整数等值类型?或者该属性仅与OP问题中的引用类型相关?