Что случилось с атрибутом [OptionalField]? - PullRequest
8 голосов
/ 30 мая 2009

Насколько я понимаю, я должен украсить нового члена в более новой версии моего класса атрибутом [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;
    }
}

1 Ответ

8 голосов
/ 30 мая 2009

BinaryFormatter в лучший раз очень хрупкий, если вы меняете вещи. Что не менее важно, существуют огромные проблемы с автоматически реализуемыми свойствами, запутыванием , переименованием, строгим присвоением имен и т. Д.

Насколько я помню, некоторые правила о [OptionalField] изменились непосредственно перед его выпуском; Я полагаю, что версия с отказоустойчивостью не сработала так легко, как планировалось.

Мой совет: если вы хотите сериализацию с поддержкой версий (то есть вы можете сериализовать ее сегодня и десериализовать с помощью следующей версии вашего приложения), тогда не используйте BinaryFormatter; это (IMO) подходит только для передачи данных между той же версией (удаленное взаимодействие, AppDomain s и т. д.).

Для работы между версиями я рекомендую сериализацию на контрактной основе; такие вещи, как XmlSerializer и DataContractSerializer (.NET 3.0), или для двоичных - protobuf-net или аналогичные инструменты. Все они на намного лучше в зависимости от версии (на самом деле, вам даже не нужно десериализовать его в один и тот же Type); плюс их можно использовать между платформами - так что вы можете сериализовать в .NET и десериализовать в java / C ++ / и т. д.

...