注:この質問は、問題について詳しく知るにつれて少し変わったので、全体を読んでください。問題がどのように発見され、最終的に解決されたかをよりよく説明しているため、元の形式のままにすることにしました。
私たちがC#やCLRを本当に理解していなかったとき、私たちのプロジェクトの歴史の最も暗い深さまでさかのぼって、私たちはタイプを作成しました。それを呼びましょうMyType。この型をclass参照型として作成しました。
MyTypeしかし、値型である必要があることが明らかになっstructたので、それを行うためにいくつかの変更を加えました。ある日まで、MyType値のコレクションを含むいくつかのデータを逆シリアル化しようとしました。そうではありませんが、それが参照型であった場合、そのコレクションは参照のコレクションでした。これで、逆シリアル化すると、コレクションはデフォルトのコンストラクターを使用して正常に逆シリアル化され、MyType後で実際の参照が逆シリアル化されると、それらは孤立し、空の値のコレクションが残ります。
そこで、「ロード時に、参照が適切に解決されるように型を参照型にマップしてから、MyTypeRef実行時と再シリアル化で使用するために実際の型に変換し直してみましょう」と考えました。したがって、(独自のバインダーを使用して)実行しましたが、残念ながら、との間の暗黙の変換があってもMyTypeRef[]変換できないことを示すエラーが発生するため、機能しませんでした。MyType[]MyTypeRefMyType
だから、私たちは立ち往生しています。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);
}