私の回答のコピー: .net の DataContract 属性と Serializable 属性の違い
上記の質問は次で終わりますが、私の答えはここよりもはるかに適しています。
「... それとも、ディープクローンを作成する別の方法ですか?」
リフレクションを介してオブジェクト構造を検査したことがあります。
ちょっとした作業で、ディープ コピー用の同様の方法を構築できます。基本的に、循環参照を検出するには Dictionary を使用する再帰的なメソッドが必要です。メソッド内では、次のようにすべてのフィールドを検査します。
private void InspectRecursively(object input,
Dictionary<object, bool> processedObjects)
{
if ((input != null) && !processedObjects.ContainsKey(input))
{
processedObjects.Add(input, true);
List<FieldInfo> fields = type.GetFields(BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic );
foreach (FieldInfo field in fields)
{
object nextInput = field.GetValue(input);
if (nextInput is System.Collections.IEnumerable)
{
System.Collections.IEnumerator enumerator = (nextInput as
System.Collections.IEnumerable).GetEnumerator();
while (enumerator.MoveNext())
{
InspectRecursively(enumerator.Current, processedObjects);
}
}
else
{
InspectRecursively(nextInput, processedObjects);
}
}
}
}
それを機能させるには、出力オブジェクトを追加する必要がありSystem.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type type)
、各フィールドの値の最も浅いコピー (参照をコピーしなくても) を作成するようなものを追加する必要があります。最後に、各フィールドを次のように設定できますfield.SetValue(input, output)
ただし、この実装は登録されたイベントハンドラーをサポートしていません。これは、逆シリアル化でもサポートされていません。さらに、クラスのコンストラクターがすべてのフィールドを設定する以外に何かを初期化する必要がある場合、階層内の各オブジェクトは壊れます。[OnDeserialized]
クラスにそれぞれの実装がある場合、最後のポイントはシリアライゼーションでのみ機能しISerializable
ます。