0

すべてのプロファイル オブジェクトを含むプロファイル ハンドラーをディスクにシリアル化する単純なアプリケーションがあります。それはうまく機能します...しかし、将来的に問題が発生することに気づきました。

次回ソフトウェアを更新すると、プロファイルが変更されたり、新しいフィールドやプロパティが追加されたり、一部のタイプが変更されたりする可能性があります。もちろん、以前のバージョンから逆シリアル化しようとすると、プログラムが壊れます。

この問題を解決する最も簡単で簡単な方法は何ですか? バイナリ ファイルにいくつかのヘッダー ビットを追加し、何らかの方法でチェックする方法があるはずだと考えています。

これが私のシリアライザーメソッドです:

private void SaveProfilesToDisk()
{
    var serializer = new BinaryFormatter();

    string filename = Path.Combine(Environment.CurrentDirectory, @"MyApp\MyApp.profiles");
    using (FileStream fileStream = File.OpenWrite(filename))
    {
        serializer.Serialize(fileStream, _profileHandler);
    }
}

そして、これは私がそれを逆シリアル化する方法です:

 private ProfileHandler LoadProfilesFromDisk()
    {
        var serializer = new BinaryFormatter();

        string filename = Path.Combine(Environment.CurrentDirectory, @"MyApp\MyApp.profiles");
        using (FileStream fileStream = File.OpenRead(filename))
        {
            return (ProfileHandler) serializer.Deserialize(fileStream);
        }
    }

保存ファイルが古くなっていることをユーザーに伝え、名前を変更/削除して新しいファイルを作成するだけで十分です。

4

1 に答える 1

1

編集: 質問を読み直すと、AssemblyResolve イベントが、デシリアライザーが解決しようとしていたアセンブリのバージョンを受け取ることに注意する価値があることに気付きました。互換性のないバージョンのメッセージだけが必要な場合は、アセンブリ名がアセンブリ名であり、バージョンが現在のバージョンとは異なる場合にトラップして、それに応じてプロンプトを表示できます。

XmlSerialization を使用するのが最も簡単な方法であることに @smoore に同意します。これは、破壊的でない変更が発生した以前のバージョンのプロファイルを逆シリアル化できるためです。XmlSerializer は、存在しないフィールドを単純に無視し、存在するフィールドを喜んで逆シリアル化します。

何らかの理由でバイナリ シリアル化が必要で、アプリが古いバージョンのオブジェクトを使用しても問題ない場合、これを行う 1 つの方法は、逆シリアル化のバージョンを気にせず、単純に一致させて逆シリアル化を試みることです。プロパティが可能でした。新しいプロパティの追加など、破壊的でない変更については、古いバージョンを問題なく逆シリアル化できるはずです。

最初にタイプ解決イベントを登録します。

AppDomain.CurrentDomain.TypeResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

次に、タイプ解決メソッドを追加し、関心のあるアセンブリについて、それらのアセンブリの現在のバージョンを返します。これは私がこのようなことをした例です:

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
            Assembly result = null;
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
                AssemblyName assemblyName = assembly.GetName();
                if (args.Name.StartsWith(assemblyName.Name)) {
                    this.LogInfo("Assembly \"" + args.Name + "\" resolved to \"" + assembly.Location + "\".");
                    result = assembly;
                    break;
                }
            }
            if(result != null){
                return result;
            }else{
                this.LogError("Assembly resolution failure. An assembly named \"" + args.Name + "\" was not found.");
                return null;
            }
        }

私の考えが正しければ、これにより型が新しいバージョンに解決され、破壊的でない変更が発生した古いバージョンを逆シリアル化できるようになります。重大な変更の場合、最も簡単な方法は、SerializationException をキャッチして、それに応じてユーザーにプロンプ​​トを表示することです。

于 2013-06-25T16:15:47.700 に答える