Перенос сериализованных объектов в новую версию - PullRequest
2 голосов
/ 04 февраля 2010

Я хочу перенести ранее сериализованные объекты из базы данных в новую схему.

Мой предыдущий объект.

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 ]

2 голосов
/ 04 февраля 2010

Я недавно сделал нечто похожее, где создал простое консольное приложение, которое позволяет преобразовывать некоторые сериализованные объекты из одной версии в другую. Я просто использовал обе версии 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 голос
/ 04 февраля 2010

1) Напишите утилиту, которая читает сериализованные объекты в старом определении объекта.

2) Утилита записывает ваши объекты в БД несериализованным способом (т. Е. С одним фрагментом данных в каждом поле и т. Д.).

Не приучайте к сериализации объектов и хранению их в постоянном хранилище для извлечения (намного) позже. Сериализация не была построена для этого.

В старые времена вы сталкивались с проблемой программистов на C: они создавали структуру в памяти, сохраняли эту структуру в файл. Тогда члены структуры изменятся, и они зададутся вопросом, как их прочитать, так как данные были закодированы по-разному.

затем появились форматы баз данных, INI-файлы и т. Д., Специально предназначенные для удовлетворения этой потребности, что позволило сохранить данные в одном формате и затем прочитать их без ошибок.

Так что не повторяйте ошибок прошлого. Сериализация была создана для облегчения кратковременного двоичного хранения и, скажем, возможности передавать объект по TCP / IP.

В худшем случае храните ваши данные в формате XML, а не в виде сериализованного двоичного потока. Кроме того, нет никаких сведений о том, что от MS известно, что сериализованные данные из одной версии .NET можно будет читать из другой. Преобразуйте ваши данные в удобочитаемый формат, пока вы можете.

...