public static T DeepClone <T>(this T obj, bool ignoreCustomSerialization = false) { ISurrogateSelector surrogate = null; var formatter = new BinarySerializationFormatter(BinarySerializationOptions.RecursiveSerializationAsFallback | BinarySerializationOptions.CompactSerializationOfStructures | BinarySerializationOptions.IgnoreTypeForwardedFromAttribute); #if NETFRAMEWORK if (RemotingServices.IsTransparentProxy(obj)) { surrogate = new RemotingSurrogateSelector(); } else #endif if (ignoreCustomSerialization) { formatter.Options |= BinarySerializationOptions.IgnoreSerializationMethods | BinarySerializationOptions.IgnoreIObjectReference | BinarySerializationOptions.IgnoreIBinarySerializable; surrogate = new CustomSerializerSurrogateSelector { IgnoreISerializable = true, IgnoreNonSerializedAttribute = true }; } formatter.SurrogateSelector = surrogate; using (var stream = new MemoryStream()) { formatter.SerializeToStream(stream, obj); stream.Position = 0L; #if NETFRAMEWORK if (surrogate is RemotingSurrogateSelector) { formatter.SurrogateSelector = null; } #endif return((T)formatter.DeserializeFromStream(stream)); } }
public void SerializeClassWithConflictingFields() { object obj = new ConflictNameChild(1, 2, 3, "Public Base", "Protected Base", "Private Base"); ISurrogateSelector surrogate = new CustomSerializerSurrogateSelector(); var bf = new BinaryFormatter(); var bsf = new BinarySerializationFormatter(); // not using surrogate: tests if the formatter can handle the situation internally DoTest(bf, null, obj, false, false, false); DoTest(bsf, null, obj, true, false, false); // using surrogate for both ways DoTest(bf, surrogate, obj, false, true, true); DoTest(bsf, surrogate, obj, true, true, true); // default serialization by surrogate: the formatter must add unique names to the serialization info // and the surrogate must resolve these names somehow (can be solved by events) //DoTest(bf, surrogate, obj, false, false, true); // SerializationException : Cannot add the same member twice to a SerializationInfo object (BF tries to add the same field names for public fields) DoTest(bsf, surrogate, obj, true, false, true); // surrogate serialization by default: the surrogate must add unique names, which should be // resolved by the formatter somehow (not really possible without hard coded handling in the formatter) //DoTest(bf, surrogate, obj, false, true, false); // Equality check failed for base public field (BF uses class name prefix for non-public fields only) DoTest(bsf, surrogate, obj, true, true, false); }
public void WriteWithSurrogate(object obj) { ISurrogateSelector surrogate = new CustomSerializerSurrogateSelector(); DoTest(new BinaryFormatter(), surrogate, obj, false, true, false); DoTest(new BinarySerializationFormatter(), surrogate, obj, true, true, false); DoTest(new BinarySerializationFormatter(BinarySerializationOptions.TryUseSurrogateSelectorForAnyType), surrogate, obj, true, false, true); }
public void ReadAndWriteWithSurrogate(object obj) { ISurrogateSelector surrogate = new CustomSerializerSurrogateSelector(); DoTest(new BinaryFormatter(), surrogate, obj, false, true, true); DoTest(new BinarySerializationFormatter(), surrogate, obj, true, true, true); DoTest(new BinarySerializationFormatter(BinarySerializationOptions.ForceRecursiveSerializationOfSupportedTypes), surrogate, obj, true, true, true); }
public void IgnoreISerializableTest() { using var obj = new DataTable("tableName", "namespaceName"); var surrogate = new CustomSerializerSurrogateSelector(); var formatter = new BinarySerializationFormatter { SurrogateSelector = surrogate }; DoTest(formatter, surrogate, obj, true, true, true); surrogate.IgnoreISerializable = true; formatter.Options = BinarySerializationOptions.IgnoreSerializationMethods; // TextInfo.OnDeserialization in .NET Core surrogate.IgnoreNonSerializedAttribute = true; DoTest(formatter, surrogate, obj, true, true, true); }
public void IgnoreNonSerializedAttributeTest() { object obj = new SerializationEventsClass { Name = "Parent" }.AddChild("Child").Parent; var surrogate = new CustomSerializerSurrogateSelector(); // Formatter now omits serialization methods. If the surrogate selector skips non-serialized fields, it will cause a problem. var formatter = new BinarySerializationFormatter(BinarySerializationOptions.IgnoreSerializationMethods) { SurrogateSelector = surrogate }; Throws<AssertionException>(() => DoTest(formatter, surrogate, obj, true, true, true), "Equality check failed"); // But if we force to serialize all fields, even non-serialized ones, the clones will be identical. surrogate.IgnoreNonSerializedAttribute = true; DoTest(formatter, surrogate, obj, true, true, true); }