about summary refs log tree commit diff
path: root/LibMatrix.EventTypes.Abstractions/Converters/EventConverterFactory.cs
blob: 3b4c4931fcb22f349ab2612b997708d67d0e9de2 (plain) (blame)
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();
        }
    }
}*/