据我所知,当我反序列化缺少这个新成员的旧版本的类时,我必须使用[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;
}
}
答案 0 :(得分:8)
BinaryFormatter
,在最佳时,如果你改变了东西,那就非常脆弱。同样重要的是,automatically implemented properties, obfuscaction存在巨大问题,重命名,强命名等等。
我记得,[OptionalField]
的一些规则在发布之前发生了变化;我希望,版本宽容的东西并不像计划的那样容易实现。
我的建议:如果您想要版本容忍序列化(即您今天可以序列化它并使用下一版本的应用程序对其进行反序列化),那么请不要使用BinaryFormatter
;这是(IMO)仅适用于在相同版本(远程处理,AppDomain
等)之间传递数据。
对于版本之间的工作,我建议基于合同的序列化;像XmlSerializer
和DataContractSerializer
(.NET 3.0),或二进制 - protobuf-net或类似工具。所有这些很多在版本容忍度方面更好(实际上,您甚至不需要将其反序列化为相同的Type
);加上它们可以在平台之间使用 - 所以你可以在.NET中序列化并在java / C ++ /等中反序列化。