据我所知,当我反序列化缺少新成员的旧版本的类时,我必须用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;
}
}发布于 2009-05-30 17:14:39
即使在最好的情况下,如果你改变了一些东西,BinaryFormatter也是非常脆弱的。尤其是,在automatically implemented properties, obfuscaction、重命名、强命名等方面存在巨大的问题。
在我的记忆中,关于[OptionalField]的一些规则就在它发布之前发生了变化;版本容忍的事情并没有像计划的那样容易,我想。
我的建议是:如果你想要版本容错的序列化(也就是,你现在可以序列化它,然后在你的应用程序的下一个版本中反序列化它),那么不要使用BinaryFormatter;这(IMO)只适用于在相同的版本(远程处理、AppDomain等)之间传递数据。
对于不同版本之间的工作,我建议使用基于契约的序列化;比如XmlSerializer和DataContractSerializer (.NET 3.0),或者用于binary - protobuf-net或类似的工具。所有这些在版本容错方面都要好得多(实际上,你甚至不需要将其反序列化到相同的Type中);另外,它们可以在平台之间使用--因此你可以在.NET中序列化,在java/C++/等中反序列化。
https://stackoverflow.com/questions/929985
复制相似问题