-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathInterfaceConverter.cs
89 lines (75 loc) · 2.65 KB
/
InterfaceConverter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using System.Reflection;
using System.Text.Json.Serialization;
namespace System.Text.Json;
public class InterfaceConverter<T> : JsonConverter<T>
where T : class
{
private static Dictionary<string, Type> _sources = new Dictionary<string, Type>();
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Utf8JsonReader readerClone = reader;
if (readerClone.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}
readerClone.Read();
if (readerClone.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException();
}
string propertyName = readerClone.GetString() ?? string.Empty;
if (propertyName != "$type")
{
throw new JsonException();
}
readerClone.Read();
if (readerClone.TokenType != JsonTokenType.String)
{
throw new JsonException();
}
string typeValue = readerClone.GetString() ?? string.Empty;
Type? entityType = GetCustomType(typeValue);
var deserialized = JsonSerializer.Deserialize(ref reader, entityType!, options);
return (T)deserialized;
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
switch (value)
{
case null:
JsonSerializer.Serialize(writer, (T)null, options);
break;
default:
{
var type = value.GetType();
using var jsonDocument = JsonDocument.Parse(JsonSerializer.Serialize(value, type, options));
writer.WriteStartObject();
writer.WriteString("$type", type.FullName);
foreach (var element in jsonDocument.RootElement.EnumerateObject())
{
element.WriteTo(writer);
}
writer.WriteEndObject();
break;
}
}
}
private static Type GetCustomType(string typeName)
{
if (_sources.ContainsKey(typeName))
{
return _sources[typeName];
}
List<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
foreach (var assembly in assemblies)
{
Type t = assembly.GetType(typeName, false);
if (t != null)
{
_sources.Add(typeName, t);
return t;
}
}
throw new ArgumentException("Type " + typeName + " doesn't exist in the current app domain");
}
}