using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using static System.Net.Mime.MediaTypeNames;
public class Building : Component<BuildingMetadata>
public string Id { get; set; }
public string tag { get; set; }
public class InnerComponent : Component<ComponentMetadata>
public string tag { get; set; }
public class BuildingMetadata : ComponentMetadata
public bool IsAttached { get; set; }
[ProtoInclude(1002, typeof(BuildingMetadata))]
public class ComponentMetadata
public string Model { get; set; }
public interface IComponent
[ProtoInclude(1002, typeof(Building))]
[ProtoInclude(1001, typeof(InnerComponent))]
public class Component<TMetadataType> : ComponentBase, IComponent where TMetadataType : ComponentMetadata, new()
public TMetadataType Metadata { get; set; } = new TMetadataType();
public string Model { get => Metadata.Model; private set { } }
[ProtoInclude(1002, typeof(Component<BuildingMetadata>))]
[ProtoInclude(1001, typeof(Component<ComponentMetadata>))]
public class ComponentBase
public string SerializedProperties { get; set; }
public IDictionary<string, InnerComponent> Components { get; set; } = new Dictionary<string, InnerComponent>();
public static void Test()
static void TestBuilding()
Metadata = new BuildingMetadata()
SerializedProperties = "Building serialized properties",
["foo"] = new InnerComponent { tag = "inner component tag" },
using var stream = new MemoryStream();
Serializer.Serialize(stream, test1);
var test2 = Serializer.Deserialize<Building>(stream);
Assert.That(test1.Id.Equals(test2.Id));
Assert.That(test1.tag.Equals(test2.tag));
Assert.AreEqual(test1.Components.Count, test2.Components.Count);
Assert.That(test1.Components.Values.Select(c => c?.tag).SequenceEqual(test2.Components.Values.Select(c => c?.tag)));
Assert.That(test1.Components.Keys.SequenceEqual(test2.Components.Keys));
Assert.AreEqual(test1.SerializedProperties, test2.SerializedProperties);
Assert.That(test1.Metadata.IsAttached == test2.Metadata.IsAttached);
Assert.That(test1.Metadata.Model.Equals(test2.Metadata.Model));
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: ");