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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/*namespace LibMatrix.EventTypes.Converters;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
public class MatrixEventConverter : JsonConverterFactory {
public override bool CanConvert(Type typeToConvert) {
Console.WriteLine(typeToConvert);
if (!typeToConvert.IsGenericType) {
return false;
}
if (typeToConvert.GetGenericTypeDefinition() != typeof(MatrixEvent<>)) {
return false;
}
return typeToConvert.GetGenericArguments()[0].IsAssignableTo(typeof(MatrixEventContent));
}
public override JsonConverter CreateConverter(
Type type,
JsonSerializerOptions options) {
Type[] typeArguments = type.GetGenericArguments();
Type keyType = typeArguments[0];
Type valueType = typeArguments[1];
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(DictionaryEnumConverterInner<,>).MakeGenericType(
[keyType, valueType]),
BindingFlags.Instance | BindingFlags.Public,
binder: null,
args: [options],
culture: null)!;
return converter;
}
private class DictionaryEnumConverterInner<TKey, TValue> :
JsonConverter<Dictionary<TKey, TValue>> where TKey : struct, Enum {
private readonly JsonConverter<TValue> _valueConverter;
private readonly Type _keyType;
private readonly Type _valueType;
public DictionaryEnumConverterInner(JsonSerializerOptions options) {
// For performance, use the existing converter.
_valueConverter = (JsonConverter<TValue>)options
.GetConverter(typeof(TValue));
// Cache the key and value types.
_keyType = typeof(TKey);
_valueType = typeof(TValue);
}
public override Dictionary<TKey, TValue> Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) {
if (reader.TokenType != JsonTokenType.StartObject) {
throw new JsonException();
}
var dictionary = new Dictionary<TKey, TValue>();
while (reader.Read()) {
if (reader.TokenType == JsonTokenType.EndObject) {
return dictionary;
}
// Get the key.
if (reader.TokenType != JsonTokenType.PropertyName) {
throw new JsonException();
}
string? propertyName = reader.GetString();
// For performance, parse with ignoreCase:false first.
if (!Enum.TryParse(propertyName, ignoreCase: false, out TKey key) &&
!Enum.TryParse(propertyName, ignoreCase: true, out key)) {
throw new JsonException(
$"Unable to convert \"{propertyName}\" to Enum \"{_keyType}\".");
}
// Get the value.
reader.Read();
TValue value = _valueConverter.Read(ref reader, _valueType, options)!;
// Add to dictionary.
dictionary.Add(key, value);
}
throw new JsonException();
}
public override void Write(
Utf8JsonWriter writer,
Dictionary<TKey, TValue> dictionary,
JsonSerializerOptions options) {
writer.WriteStartObject();
foreach ((TKey key, TValue value) in dictionary) {
string propertyName = key.ToString();
writer.WritePropertyName
(options.PropertyNamingPolicy?.ConvertName(propertyName) ?? propertyName);
_valueConverter.Write(writer, value, options);
}
writer.WriteEndObject();
}
}
}*/
|