none
共有メモリにオブジェクトのリストをシリアライズ、デシリアライズしたい RRS feed

  • 質問

  • いつもお世話になっております。arubi-momoと申します。

    開発環境は次の通りです。

    Windows7 64bit VisualStudio2017 C#

    以前も質問させていただいた共有メモリの件で、Deserializeができずに困っています。

    やりたいことは、List<T>形式のリストをそのまま共有メモリに保存し、別のアプリケーションから読み出したいです。

    // テストクラス
    [Serializable()]
    public class testInfo
    {
        public string name { get; set; }
        public string type { get; set; }
        public int iValue { get; set; }
        public float fValue { get; set; }
    
        // コンストラクタ
        public ValInfo() { }
    }
    
    //=============
    //共有メモリ登録処理
    //=============
    // 共有メモリに登録したいオブジェクト配列を宣言
    List<testInfo> infos = new List<testInfo>();
    
    // 共有メモリ生成
    private MemoryMappedFile m_mmf  = MemoryMappedFile.CreateNew("Global\\TEST", 1024, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, security, HandleInheritability.None);
    
    // フォーマッターの宣言
    var formatter = new BinaryFormatter();
    // 共有メモリに書き込み
    using (MemoryMappedViewStream stream = m_mmf.CreateViewStream())
    {
        // 共有メモリへ登録
        formatter.Serialize(stream, infos );
        stream.Flush();
    }
    
    //=============
    //共有メモリ読み込み処理
    //=============
    // 共有メモリから読み出した情報を取得するための配列
    List<testInfo> infos = new List<testInfo>();
    
    // フォーマッターの宣言
    var formatter = new BinaryFormatter();
    // 共有メモリを開く
    using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("Global\\TEST"))
    {
        // 共有メモリの内容を取得
        using (MemoryMappedViewStream stream = mmf.CreateViewStream())
        {
            object obj = formatter.Deserialize(stream); // ←ここでエラー
            var objs = obj as List<testInfo>;
            
            // objsから情報を取得する処理
            ・・・・
        }
    }

    共有メモリのSerializeまではうまくいくのですが、Deserializeのところでアセンブリが存在しない旨のエラーが発生します。

    デシリアライズができない原因がわからず困っております。

    原因にお心当たりのある方がいらっしゃいましたら、何卒、ご教示いただけますようお願いいたします。

    2019年1月22日 15:04

回答

  • BinaryFormatterはアセンブリが一致しないと逆シリアライズできません。
    異なるアプリケーションでそれぞれでtestInfoクラスを定義していたら型情報も異なることになります。

    BinaryFormatterを使用したいのであれば、クラスtestInfoをDLLにてして、書き込みするアプリケーションと読み出すアプリケーションの両方からDLLを参照しましょう。

    どうしてもDLLにできないというのであれば、以下のようなSerializationBinderを作って偽装すればできないことはないですが、ネストしてるクラスがめんどくさいですよ。

    public class Binder<T> : System.Runtime.Serialization.SerializationBinder
    {
        public override Type BindToType(string assemblyName, string typeName)
        {
            if (typeName.Contains("System.Collections.Generic.List"))
            {
                return typeof(List<T>);
            }
            else
            {
                return typeof(T);
            }
        }
    }
    
    //var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
    //formatter.Binder = new Binder<testInfo>();//読み出し側のtypeInfoクラスで偽装


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク arubi_momo 2019年1月24日 1:07
    2019年1月22日 20:24

すべての返信

  • BinaryFormatterはアセンブリが一致しないと逆シリアライズできません。
    異なるアプリケーションでそれぞれでtestInfoクラスを定義していたら型情報も異なることになります。

    BinaryFormatterを使用したいのであれば、クラスtestInfoをDLLにてして、書き込みするアプリケーションと読み出すアプリケーションの両方からDLLを参照しましょう。

    どうしてもDLLにできないというのであれば、以下のようなSerializationBinderを作って偽装すればできないことはないですが、ネストしてるクラスがめんどくさいですよ。

    public class Binder<T> : System.Runtime.Serialization.SerializationBinder
    {
        public override Type BindToType(string assemblyName, string typeName)
        {
            if (typeName.Contains("System.Collections.Generic.List"))
            {
                return typeof(List<T>);
            }
            else
            {
                return typeof(T);
            }
        }
    }
    
    //var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
    //formatter.Binder = new Binder<testInfo>();//読み出し側のtypeInfoクラスで偽装


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク arubi_momo 2019年1月24日 1:07
    2019年1月22日 20:24
  • gekkaさま

    いつも大変お世話になっております。

    アセンブリが存在しないというのはそういう意味だったんですね!恥ずかしながら今ようやく認識しました。

    DLLを作成できればそれが一番早そうだなと思いますので、その方向で進めたいと思います。

    また何か行き詰った時にはご相談させていただくかもしれません。

    本当にありがとうございました。

    今後ともなにとぞ、よろしくお願いいたします。


    2019年1月23日 14:06