[OptionalField] 属性怎么了?

发布于 2024-07-23 18:54:18 字数 1577 浏览 17 评论 0 原文

据我了解,当我反序列化缺少此新成员的类的旧版本时,我必须使用 [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;
    }
}

As I understand it I have to adorn a new member in a newer version of my class with the [OptionalField] Attribute when I deserialize an older version of my class that lacks this newer member.

However, the code below throws no exception while the InnerTranslator property was added after serializing the class. I check for the property to be null in the onDeserialization method (which confirms that it was not serialized),but I would have expected the code to throw an exception because of that.
Is the [OptionalField] Attribute itself optional?

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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清欢 2024-07-30 18:54:18

如果您进行更改,BinaryFormatter最好的情况下会非常脆弱。 尤其重要的是,自动实现的属性、混淆存在巨大问题,重命名,强命名等。

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

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

对于版本之间的工作,我建议基于契约的序列化; 例如 XmlSerializerDataContractSerializer (.NET 3.0),或二进制 - protobuf-net 或类似工具。 所有这些在版本容错性方面都更好(事实上,您甚至不需要将其反序列化为相同的类型); 另外,它们可以在平台之间使用 - 因此您可以在 .NET 中序列化并在 java/C++/等中反序列化。

BinaryFormatter is, at the best of times, very brittle if you change things. Not least, there are huge problems with automatically implemented properties, obfuscaction, renaming, strong naming, etc.

As I recall, some of the rules about [OptionalField] changed just before it was released; the version tolerant thing didn't really work out as easily as had been planned, I expect.

My advice: if you want version tolerant serialization (i.e. you can serialize it today and deserialize it with the next version of your app), then don't use BinaryFormatter; this is (IMO) only suitable for passing data between the same version (remoting, AppDomains, etc).

For work between versions, I recommend contract-based serialization; things like XmlSerializer and DataContractSerializer (.NET 3.0), or for binary - protobuf-net or similar tools. All of these are much better at version tolerance (indeed, you don't even need to deserialize it into the same Type); plus they can be used between platforms - so you can serialize in .NET and deserialize in java/C++/etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文