Skip to content

Instantly share code, notes, and snippets.

@bahusoid
Last active April 12, 2021 20:23
Show Gist options
  • Save bahusoid/ecdd9119c30fef5e08585761a015b96b to your computer and use it in GitHub Desktop.
Save bahusoid/ecdd9119c30fef5e08585761a015b96b to your computer and use it in GitHub Desktop.
Workaround for deserialization exception (broken)
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace ConsoleApp12
{
public static class Program
{
public static void Main()
{
var myClass = new MyProxy
{
Id = 1,
Ref = new MyProxy
{
Id = 2,
Ref = new MyProxy()
{
Id = 3,
}
}
};
var result1 = SpoofSerialization(myClass);
Console.WriteLine("Ok without circular references");
// Add circular reference
myClass.Ref.Ref = myClass;
var result2 = SpoofSerialization(myClass);
Console.WriteLine(result2.Ref.Ref == result2 ? "Works too!": "Fails to restore circular reference!" );
}
[Serializable]
public class MyProxy : ISerializable
{
private MyProxyObjWrapper _proxyRef;
public int Id { get; set; }
public MyProxy Ref { get; set; }
public MyProxy()
{
_proxyRef = new MyProxyObjWrapper(this);
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.SetType(typeof(MyProxyObjRef));
// Use IObjectReference only inside proxy
new MyProxyObjRef(this).GetObjectData(info, context);
}
[Serializable]
class MyProxyObjRef : MyProxyObjWrapper, IObjectReference
{
public MyProxyObjRef(MyProxy myProxy) : base(myProxy)
{
}
private protected MyProxyObjRef(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
[Serializable]
class MyProxyObjWrapper : ISerializable
{
private MyProxy _myProxy;
public MyProxyObjWrapper(MyProxy myProxy)
{
_myProxy = myProxy;
}
private protected MyProxyObjWrapper(SerializationInfo info, StreamingContext context)
{
_myProxy = new MyProxy
{
Id = info.GetInt32(nameof(MyProxy.Id)),
Ref = ((MyProxyObjWrapper) info.GetValue(nameof(MyProxy.Ref), typeof(MyProxyObjWrapper)))?._myProxy,
};
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue(nameof(_myProxy.Id), _myProxy.Id);
// Use wrapper
info.AddValue(nameof(_myProxy.Ref), _myProxy.Ref?._proxyRef, typeof(MyProxyObjWrapper));
}
public object GetRealObject(StreamingContext context)
{
return _myProxy;
}
}
}
private static T SpoofSerialization<T>(T session)
{
var formatter = new BinaryFormatter();
var stream = new MemoryStream();
formatter.Serialize(stream, session);
stream.Position = 0;
return (T) new BinaryFormatter().Deserialize(stream);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment