using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public interface IObjectFactory<out T>
bool CanCreate(Type type);
public class ObjectFactoryContractResolver : DefaultContractResolver
readonly IObjectFactory<object> factory;
public ObjectFactoryContractResolver(IObjectFactory<object> factory) => this.factory = factory ?? throw new ArgumentNullException(nameof(factory));
protected override JsonContract CreateContract(Type objectType)
var contract = base.CreateContract(objectType);
if (factory.CanCreate(objectType))
contract.DefaultCreator = () => factory.Create(objectType);
contract.DefaultCreatorNonPublic = false;
public class InterfaceFactory : IObjectFactory<IInterface>
public InterfaceFactory(string runtimeId) => this.RuntimeId = runtimeId;
string RuntimeId { get; }
public bool CanCreate(Type type) => !type.IsAbstract && typeof(IInterface).IsAssignableFrom(type);
public IInterface Create(Type type) => type switch
var t when t == typeof(A) => new A(RuntimeId),
var t when t == typeof(B) => new B(RuntimeId),
_ => throw new NotImplementedException(type.ToString()),
public interface IInterface
public string RuntimeId { get; }
public class A : IInterface
[JsonIgnore] public string RuntimeId { get; }
internal A(string id) => this.RuntimeId = id;
public int content { get; set; }
public class B : IInterface
[JsonIgnore] public string RuntimeId { get; }
internal B(string id) => this.RuntimeId = id;
public float data { get; set; }
public static void Test()
var valueToInject = "some value to inject";
var factory = new InterfaceFactory(valueToInject);
List<IInterface> list = new() { factory.Create(typeof(A)), factory.Create(typeof(B)) };
var resolver = new ObjectFactoryContractResolver(factory)
NamingStrategy = new CamelCaseNamingStrategy(),
var settings = new JsonSerializerSettings
ContractResolver = resolver,
TypeNameHandling = TypeNameHandling.Auto,
var json = JsonConvert.SerializeObject(list, Formatting.Indented, settings);
var list2 = JsonConvert.DeserializeObject<List<IInterface>>(json, settings);
Assert.That(list.Select(i => i.GetType()).SequenceEqual(list2.Select(i => i.GetType())));
Assert.That(list2.All(i => i.RuntimeId == valueToInject));
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Namespace, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");