Я создал класс Car, который я использую для хранения предустановленных сериализованных версий Cars со всеми их различными свойствами и тем, что у вас есть.
По мере выполнения моей программы я понял, что если я добавлю или удалю свойство Car, каждый ранее сериализованный файл станет нечитаемым. Это, как вы понимаете, проблема.
Как я могу обновить свой класс, не аннулируя все предыдущие файлы?
-- Щелчок
Обновление: я добавил пример кода того, что я делаю Проблема возникает, если я добавляю/удаляю свойство и пытаюсь десериализовать файл.
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.IO;
using System;
namespace MyCars
{
[Serializable]
public class Car
{
public string Name { get; set; }
public double TopSpeed { get; set; }
public Car(string name, double topspeed)
{
Name = name;
TopSpeed = topspeed;
}
}
public static class Serializer
{
public static bool LoadCar(string filePath, out Car car)
{
Stream TestFileStream = File.OpenRead(filePath);
BinaryFormatter serializer = new BinaryFormatter();
try
{
car = (Car)serializer.Deserialize(TestFileStream);
}
catch (Exception ex)
{
Console.WriteLine("Could not deserialize");
TestFileStream.Close();
car = null;
return false;
}
return true;
}
public static bool SaveCar(string filePath, Car car)
{
Stream TestFileStream = File.Create(filePath);
BinaryFormatter serializer = new BinaryFormatter();
serializer.Serialize(TestFileStream, car);
TestFileStream.Close();
return true;
}
}
}
Как вы его десериализуете?
Пожалуйста, опубликуйте свой код
Использовать сериализацию json и игнорировать отсутствующие свойства
Я должен использовать двоичную сериализацию для этой конкретной цели. Я не могу использовать JSON. Я просто использую встроенный атрибут [Serializable]. Я опубликую пример кода, он не показался мне нужным, так как мне он показался чисто теоретическим, извиняюсь.
Единственный способ - включить номер версии в имя файла, чтобы вы могли иметь разные версии классов для прямой/обратной совместимости.
@ClicketyClackety не использует BinaryFormatter. Он не только очень хрупкий, но и ненадежный и непоправимый. На странице документации есть очень серьезное предупреждение, объясняющее, что BinaryFormatter is insecure and can't be made secure.
этот класс планируется удалить уже много лет, и он даже не был добавлен в .NET Core 1.0. Он был добавлен позже только для целей совместимости с ухудшенной производительностью.
@ClicketyClackety, чтобы увидеть, насколько серьезно MS относится к этому Методы сериализации BinaryFormatter устарели и запрещены в приложениях ASP.NET. Как и в исключениях во время выполнения, они устарели. Вместо этого используйте буферы протокола
Спасибо @PanagiotisKanavos, я никогда не замечал этих предупреждений. Я думаю, я мог бы использовать xml/json и хранить биты данных, которые мне нужны, чтобы быть двоичными внутри них, сохраняя при этом текст в виде строк и т. д.
@ClicketyClackety protobuf сохраняет типы, даже сложные. Вам также не нужно беспокоиться о фактической форме, поскольку она поддерживается на нескольких платформах и на большинстве языков. Вы можете сериализовать в C# и десериализовать в Java, JavaScript, Go, C++, Python. Изменения схемы поддерживаются, если вы соблюдаете некоторые правила. Посмотрите введение в C#, например
Двоичная сериализация, реализованная System.Runtime.Serialization.Formatters.Binary
, представляет собой двоичный формат без схемы. Это означает, что если сериализатор увидит поле int
, он запишет 4 байта в файл, как и все другие поддерживаемые типы. Это очень быстро, но не гибко.
Это отличается от сериализатора, который также записывает схему, которая записывает 4 байта, а также имя поля, поэтому позже десериализатор может смешивать и сопоставлять. Как вы можете себе представить, это медленнее, но гораздо более гибко.
Пока вы придерживаетесь первого, просто не меняйте схему. Там не так много еще вы можете сделать с ним.
Вот почему все собираются (и уже рекомендовали) использовать сериализатор схемы, такой как JSON, BSON (двоичный json), протобуфер Google, XML, базу данных Sql или Nosql, что угодно еще на самом деле, особенно во время разработки, когда схемы классов меняйте часто.
Спасибо за это, я вообще не знал. Это очень полезно знать. Я взглянул на интерфейс ISerializer в MSDN:learn.microsoft.com/en-us/dotnet/api/… Я предполагаю, что даже если двоичный файл не содержит схемы, я могу вставить свои собственные уловы и решить эти вопросы?
Вы можете взять на себя автоматический процесс и реализовать свой собственный, это правильно. Одна проблема, с которой вы столкнетесь, заключается в том, что у вас также нет недостающей информации, вы не знаете, десериализуете ли вы версию со свойством car или нет. И будет только хуже, если у вас будет больше изменений в типе.
Спасибо, Блинди, все это были отличные моменты. И спасибо всем остальным, теперь я, скорее всего, изменю свое решение :)
Тогда не использовать двоичную сериализацию?