using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
this.runtimeId = Interlocked.Increment(ref nextId);
public int RuntimeId { get { return runtimeId; } }
public override string ToString()
return GetType().Name + ": " + RuntimeId.ToString();
foreach (var sprite in SpriteSurrogate.Sprites)
if (object.ReferenceEquals(this, sprite))
public static void Test()
SpriteSurrogate.AddSprite("1", new Sprite());
SpriteSurrogate.AddSprite("2", new Sprite());
SpriteSurrogate.AddSprite("3", new Sprite());
SpriteSurrogate.AddSprite("4", new Sprite());
var root = SpriteSurrogate.Sprites.Select((s, i) => new Displayable { icon = s, name = "hello " + i.ToString() }).Concat(new [] { new Displayable { name = "empty" } }).ToList();
var selector = new SurrogateSelector();
var spriteSurrogate = new SpriteSurrogate();
spriteSurrogate.Register(selector);
BinaryFormatter binaryFormatter = new BinaryFormatter(selector, new StreamingContext());
var root2 = Copy(root, binaryFormatter);
Assert.IsTrue(root.Select(d => d.icon).SequenceEqual(root2.Select(d => d.icon)));
Console.WriteLine("{0} deserialized successfully. ", root2);
Console.WriteLine("Result: ");
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(root, Newtonsoft.Json.Formatting.Indented));
public static T Copy<T>(T original, BinaryFormatter binaryFormatter)
using (MemoryStream memoryStream = new MemoryStream())
binaryFormatter.Serialize(memoryStream, original);
memoryStream.Seek(0, SeekOrigin.Begin);
return (T)binaryFormatter.Deserialize(memoryStream);
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
throw new AssertionFailedException("failed");
class ObjectReferenceProxy<T> : IObjectReference
public T RealObject { get; set; }
#region IObjectReference Members
object IObjectReference.GetRealObject(StreamingContext context)
public sealed class SpriteSurrogate : ObjectLookupSurrogate<string, Sprite>
static Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>();
static Dictionary<Sprite, string> spriteNames = new Dictionary<Sprite, string>();
public static void AddSprite(string name, Sprite sprite)
if (name == null || sprite == null)
throw new ArgumentNullException();
sprites.Add(name, sprite);
spriteNames.Add(sprite, name);
public static IEnumerable<Sprite> Sprites
protected override string GetId(Sprite realObject)
return spriteNames[realObject];
protected override Sprite GetRealObject(string id)
public abstract class ObjectLookupSurrogate<TId, TRealObject> : ISerializationSurrogate where TRealObject : class
public void Register(SurrogateSelector selector)
foreach (var type in Types)
selector.AddSurrogate(type, new StreamingContext(StreamingContextStates.All), this);
yield return typeof(TRealObject);
yield return typeof(ObjectReferenceProxy<TRealObject>);
protected abstract TId GetId(TRealObject realObject);
protected abstract TRealObject GetRealObject(TId id);
#region ISerializationSurrogate Members
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
var original = (TRealObject)obj;
var id = GetId(original);
info.SetType(typeof(ObjectReferenceProxy<TRealObject>));
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
var wrapper = (ObjectReferenceProxy<TRealObject>)obj;
var id = (TId)info.GetValue("id", typeof(TId));
wrapper.RealObject = GetRealObject(id);
public static void Main()