注:この質問は、問題について詳しく知るにつれて少し変わったので、全体を読んでください。問題がどのように発見され、最終的に解決されたかをよりよく説明しているため、元の形式のままにすることにしました。
私たちがC#やCLRを本当に理解していなかったとき、私たちのプロジェクトの歴史の最も暗い深さまでさかのぼって、私たちはタイプを作成しました。それを呼びましょうMyType
。この型をclass
参照型として作成しました。
MyType
しかし、値型である必要があることが明らかになっstruct
たので、それを行うためにいくつかの変更を加えました。ある日まで、MyType
値のコレクションを含むいくつかのデータを逆シリアル化しようとしました。そうではありませんが、それが参照型であった場合、そのコレクションは参照のコレクションでした。これで、逆シリアル化すると、コレクションはデフォルトのコンストラクターを使用して正常に逆シリアル化され、MyType
後で実際の参照が逆シリアル化されると、それらは孤立し、空の値のコレクションが残ります。
そこで、「ロード時に、参照が適切に解決されるように型を参照型にマップしてから、MyTypeRef
実行時と再シリアル化で使用するために実際の型に変換し直してみましょう」と考えました。したがって、(独自のバインダーを使用して)実行しましたが、残念ながら、との間の暗黙の変換があってもMyTypeRef[]
変換できないことを示すエラーが発生するため、機能しませんでした。MyType[]
MyTypeRef
MyType
だから、私たちは立ち往生しています。MyType
参照型のコレクションとしてシリアル化されたコレクションを取得して、値型のコレクションとして逆シリアル化するにはどうすればよいMyType
ですか?
更新
いくつかの調査(以下のコメントとコードを参照)は、実際の問題を引き起こしたのは、新しいものの不変の性質であり、シリアル化にMyType
使用されていることを示しています。ISerializable
なぜそうなるのかはまだわかりませんが、のprivate
代わりにsetアクセサーを使用するISerializable
と、新しいMyType
ものが古いものをロードします(ISerializable
使用するとインターフェイスが呼び出されますが、コレクションにはデフォルト値しか含まれていません)。
いくつかのコード
// Use a List<T> in a class that also implements ISerializable and
// save an instance of that class with a BinaryFormatter (code omitted)
// Save with this one.
[Serializable]
public class MyType
{
private string test;
public string Test
{
get { return this.test; }
set { this.test = value; }
}
public MyType()
{
}
}
// Load with this one.
[Serializable]
public class MyType : ISerializable
{
private string test;
public string Test
{
get { return this.test; }
set { this.test = value; }
}
public MyType()
{
}
public MyType(SerializationInfo info, StreamingContext context)
{
info.AddValue("test", this.test);
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
this.test = info.GetString("test");
}
}
ロードするとき、要素はすべてnullであることに注意してください。2番目の定義から削除ISerializable
し、ロードするとすべてが機能します。ロードコードをオンに変更class
すると、同じ動作が表示されます。struct
これは、コレクションが設定されたアクセサーを使用してのみ正常に逆シリアル化されるかのようです。
更新2
それで、私は問題を見つけました(以下の私の答えを参照してください)が、私の質問を読んで誰かが答えを知っているとは思えません。当時重要だとさえ気づかなかった重要な詳細を見逃しました。助けようとした人たちに心からお詫び申し上げます。
ロードMyType
されたコレクションは、の間にすぐに別のコレクションにコピーされGetObjectData
ます。以下の答えは、これが重要であることが判明した理由を説明しています。完全な例を提供する、上記のサンプルコードに追加するサンプルコードを次に示します。
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
this.myTypeCollection = new List<MyType>();
var loadedCollection = (List<MyType>)info.GetValue(
"myTypeCollection",
typeof(List<MyType>));
this.myTypeCollection.AddRange(loadedCollection);
}