using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json.Serialization;
public static void Main()
Assembly thing = new Assembly
Parts = new List<IWidget>
Parts = new List<IWidget>
new Bolt { Name = "UB1", HeadSize = 2, Length = 6 },
new Washer { Name = "UW1", Thickness = 1 },
new Nut { Name = "UN1", Size = 2 }
Parts = new List<IWidget>
new Bolt { Name = "LB1", HeadSize = 3, Length = 5 },
new Washer { Name = "LW1", Thickness = 2 },
new Washer { Name = "LW2", Thickness = 1 },
new Nut { Name = "LN1", Size = 3 }
var settings = new JsonSerializerSettings
TypeNameHandling = TypeNameHandling.Objects,
Formatting = Formatting.Indented,
ContractResolver = new CustomResolver(),
SerializationBinder = new CustomSerializationBinder(),
Console.WriteLine("----- Serializing widget tree to JSON -----");
string json = JsonConvert.SerializeObject(thing, settings);
Console.WriteLine("----- Deserializing JSON back to widgets -----");
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
using (StreamReader sr = new StreamReader(stream))
using (JsonTextReader reader = new JsonTextReader(sr))
var serializer = JsonSerializer.Create(settings);
var widget = serializer.Deserialize<IAssembly>(reader);
Console.WriteLine(widget.ToString(""));
public class CustomSerializationBinder : ISerializationBinder
Dictionary<string, Type> AliasToTypeMapping { get; set; }
Dictionary<Type, string> TypeToAliasMapping { get; set; }
public CustomSerializationBinder()
TypeToAliasMapping = new Dictionary<Type, string>
{ typeof(Assembly), "A" },
AliasToTypeMapping = new Dictionary<string, Type>
{ "A", typeof(IAssembly) },
{ "W", typeof(IWasher) },
public void BindToName(Type serializedType, out string assemblyName, out string typeName)
var alias = TypeToAliasMapping[serializedType];
Console.WriteLine("Binding type " + serializedType.Name + " to alias " + alias);
public Type BindToType(string assemblyName, string typeName)
var type = AliasToTypeMapping[typeName];
Console.WriteLine("Binding alias " + typeName + " to type " + type);
public Dictionary<Type, Type> ServiceToComponentMapping { get; set; }
ServiceToComponentMapping = new Dictionary<Type, Type>
{ typeof(IAssembly), typeof(Assembly) },
{ typeof(IBolt) , typeof(Bolt) },
{ typeof(IWasher) , typeof(Washer) },
{ typeof(INut) , typeof(Nut) },
public object Resolve(Type serviceType)
var componentType = ServiceToComponentMapping[serviceType];
var instance = Activator.CreateInstance(componentType);
public class CustomResolver : DefaultContractResolver
private MockIoc _ioc = new MockIoc();
protected override JsonObjectContract CreateObjectContract(Type objectType)
JsonObjectContract contract = base.CreateObjectContract(objectType);
Console.WriteLine("Created a contract for '" + objectType.Name + "'.");
contract.DefaultCreator = () =>
var instance = _ioc.Resolve(objectType);
Console.WriteLine("Created a '" + objectType.Name + "' instance.");
string ToString(string indent = "");
public interface IAssembly : IWidget { }
public class Assembly : IAssembly
public string Name { get; set; }
public List<IWidget> Parts { get; set; }
public string ToString(string indent = "")
var sb = new StringBuilder();
sb.AppendLine(indent + "Assembly " + Name + ", containing the following parts:");
foreach (IWidget part in Parts)
sb.AppendLine(part.ToString(indent + " "));
public interface IBolt : IWidget { }
public class Bolt : IBolt
public string Name { get; set; }
public int HeadSize { get; set; }
public int Length { get; set; }
public string ToString(string indent = "")
return indent + "Bolt " + Name + " , head size + " + HeadSize + ", length "+ Length;
public interface IWasher : IWidget { }
public class Washer : IWasher
public string Name { get; set; }
public int Thickness { get; set; }
public string ToString(string indent = "")
return indent+ "Washer "+ Name + ", thickness " + Thickness;
public interface INut : IWidget { }
public string Name { get; set; }
public int Size { get; set; }
public string ToString(string indent = "")
return indent + "Nut " +Name + ", size " + Size;