Перенос сериализованных объектов в новую версию
Я хотел бы перенести ранее сериализованные объекты из базы данных в новую схему.
Мой предыдущий объект.
Public interface MyReport
{
string Id { get; set;}
string Name { get; set;}
Dictionary<string, string> PropColl { get; set;}
}
Но по некоторым причинам нам пришлось внести изменения в интерфейс
Public interface IMarkme
{
}
Public interface MyReport<T> where T : Imarkme
{
string Id { get; set;}
string Name { get; set;}
T ExtendedProp { get; set;}
}
Public NewProp : Imarkme
{
/// some code here
}
Итак, как вы можете видеть, мой интерфейс был изменен, и я хотел бы перенести мои сериализованные объекты, которые были сериализованы на основе MyReport, в MyReport. Может ли кто-нибудь предоставить мне информацию о том, какую утилиту я должен стремиться написать, что может помочь мне достичь миграции моего сериализованный объект для новой модифицированной версии интерфейса.
Спасибо, AG
2 ответа
На самом деле я недавно сделал нечто подобное, где я создал простое консольное приложение, чтобы можно было преобразовывать некоторые сериализованные объекты из одной версии в другую. Я просто использовал обе версии библиотеки DLL и рефлексии для чтения и записи значений различных свойств. Возможно, вы найдете это полезным для вдохновения;)
static void Main(string[] args)
{
object test;
AppDomain.CurrentDomain.AssemblyResolve += domain_AssemblyResolve;
using (var con = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand())
{
cmd.CommandText = "select top 1 Data_Blob from dbo.Serialized";
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
con.Open();
var blob = (byte[])cmd.ExecuteScalar();
var bf = new BinaryFormatter();
var stream = new MemoryStream(blob);
bf.AssemblyFormat = FormatterAssemblyStyle.Full;
test = bf.Deserialize(stream);
}
}
var objNewVersion = Activator.CreateInstance(Type.GetType("ObjectGraphLibrary.Test, ObjectGraphLibrary, Version=1.0.0.10, Culture=neutral, PublicKeyToken=33c7c38cf0d65826"));
var oldType = test.GetType();
var newType = objNewVersion.GetType();
var oldName = (string) oldType.GetProperty("Name").GetValue(test, null);
var oldAge = (int) oldType.GetProperty("Age").GetValue(test, null);
newType.GetProperty("Name").SetValue(objNewVersion, oldName, null);
newType.GetProperty("DateOfBirth").SetValue(objNewVersion, DateTime.Now.AddYears(-oldAge), null);
Console.Read();
}
static Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var assName = new AssemblyName(args.Name);
var uriBuilder = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
var assemblyPath = Uri.UnescapeDataString(uriBuilder.Path);
var codeBase = Path.GetDirectoryName(assemblyPath);
var assPath = Path.Combine(codeBase, string.Format("old\\{0}.{1}.{2}.{3}\\{4}.dll", assName.Version.Major,
assName.Version.Minor, assName.Version.Build,
assName.Version.Revision, assName.Name));
return File.Exists(assPath) ? Assembly.LoadFile(assPath) : null;
}
1) Написать утилиту, которая читает сериализованные объекты в старом определении объекта.
2) Утилита записывает ваши объекты в БД несериализованным способом (т.е. с одним фрагментом данных в каждом поле и т. Д.).
Не привыкайте к привычке сериализации объектов и хранению их в постоянном хранилище для извлечения (намного) позже. Сериализация не была построена для этого.
В старые времена вы сталкивались с проблемой программистов на C: они создают структуру в памяти, сохраняют эту структуру в файл. Тогда члены структуры изменятся, и они зададутся вопросом, как их прочитать, так как данные были закодированы по-разному.
Затем появились форматы баз данных, INI-файлы и т. д., специально предназначенные для решения этой задачи, поэтому сохранение данных в одном формате и возможность их чтения без ошибок.
Так что не повторяйте ошибок прошлого. Сериализация была создана для облегчения кратковременного двоичного хранения и возможности, скажем, передавать объект по TCP/IP.
В худшем случае храните ваши данные как XML, а не как сериализованный двоичный поток. Кроме того, нет никаких сведений о том, что от MS известно, что сериализованные данные из одной версии.NET можно будет читать из другой. Преобразуйте ваши данные в удобочитаемый формат, пока вы можете.