diff --git a/src/Discord.Net.Core/API/Common/Message.cs b/src/Discord.Net.Core/API/Common/Message.cs index 52de6f97b..2c19780b1 100644 --- a/src/Discord.Net.Core/API/Common/Message.cs +++ b/src/Discord.Net.Core/API/Common/Message.cs @@ -27,7 +27,7 @@ namespace Discord.API [JsonProperty("mention_everyone")] public Optional MentionEveryone { get; set; } [JsonProperty("mentions")] - public Optional[]> UserMentions { get; set; } + public Optional[]> UserMentions { get; set; } [JsonProperty("mention_roles")] public Optional RoleMentions { get; set; } [JsonProperty("attachments")] diff --git a/src/Discord.Net.Core/API/ObjectOrId.cs b/src/Discord.Net.Core/API/EntityOrId.cs similarity index 71% rename from src/Discord.Net.Core/API/ObjectOrId.cs rename to src/Discord.Net.Core/API/EntityOrId.cs index 813aff906..01ccdcb22 100644 --- a/src/Discord.Net.Core/API/ObjectOrId.cs +++ b/src/Discord.Net.Core/API/EntityOrId.cs @@ -1,16 +1,16 @@ namespace Discord.API { - public struct ObjectOrId + public struct EntityOrId { public ulong Id { get; } public T Object { get; } - public ObjectOrId(ulong id) + public EntityOrId(ulong id) { Id = id; Object = default(T); } - public ObjectOrId(T obj) + public EntityOrId(T obj) { Id = 0; Object = obj; diff --git a/src/Discord.Net.Core/Net/Converters/UInt64ArrayConverter.cs b/src/Discord.Net.Core/Net/Converters/ArrayConverter.cs similarity index 54% rename from src/Discord.Net.Core/Net/Converters/UInt64ArrayConverter.cs rename to src/Discord.Net.Core/Net/Converters/ArrayConverter.cs index a5c2d2096..e33af2e23 100644 --- a/src/Discord.Net.Core/Net/Converters/UInt64ArrayConverter.cs +++ b/src/Discord.Net.Core/Net/Converters/ArrayConverter.cs @@ -1,28 +1,38 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; -using System.Globalization; namespace Discord.Net.Converters { - internal class UInt64ArrayConverter : JsonConverter + internal class ArrayConverter : JsonConverter { - public static readonly UInt64ArrayConverter Instance = new UInt64ArrayConverter(); + public static ArrayConverter Instance; + + private readonly JsonConverter _innerConverter; public override bool CanConvert(Type objectType) => true; public override bool CanRead => true; public override bool CanWrite => true; + public ArrayConverter(JsonConverter innerConverter) + { + _innerConverter = innerConverter; + } + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - var result = new List(); + var result = new List(); if (reader.TokenType == JsonToken.StartArray) { reader.Read(); while (reader.TokenType != JsonToken.EndArray) { - ulong id = ulong.Parse((string)reader.Value, NumberStyles.None, CultureInfo.InvariantCulture); - result.Add(id); + T obj; + if (_innerConverter != null) + obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer); + else + obj = serializer.Deserialize(reader); + result.Add(obj); reader.Read(); } } @@ -33,9 +43,15 @@ namespace Discord.Net.Converters if (value != null) { writer.WriteStartArray(); - var a = (ulong[])value; + var a = (T[])value; for (int i = 0; i < a.Length; i++) - writer.WriteValue(a[i].ToString(CultureInfo.InvariantCulture)); + { + if (_innerConverter != null) + _innerConverter.WriteJson(writer, a[i], serializer); + else + serializer.Serialize(writer, a[i], typeof(T)); + } + writer.WriteEndArray(); } else diff --git a/src/Discord.Net.Core/Net/Converters/DiscordContractResolver.cs b/src/Discord.Net.Core/Net/Converters/DiscordContractResolver.cs index 0a61806b6..26b9beb76 100644 --- a/src/Discord.Net.Core/Net/Converters/DiscordContractResolver.cs +++ b/src/Discord.Net.Core/Net/Converters/DiscordContractResolver.cs @@ -23,7 +23,7 @@ namespace Discord.Net.Converters if (propInfo != null) { JsonConverter converter; - var type = propInfo.PropertyType; + Type type = propInfo.PropertyType; Type genericType = type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : null; if (genericType == typeof(Optional<>)) @@ -37,29 +37,7 @@ namespace Discord.Net.Converters var shouldSerializeDelegate = (Func)shouldSerialize.CreateDelegate(typeof(Func)); property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate); - var converterType = typeof(OptionalConverter<>).MakeGenericType(innerTypeOutput).GetTypeInfo(); - var instanceField = converterType.GetDeclaredField("Instance"); - converter = instanceField.GetValue(null) as JsonConverter; - if (converter == null) - { - var innerConverter = GetConverter(propInfo, innerTypeOutput); - converter = converterType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter; - instanceField.SetValue(null, converter); - } - } - else if (genericType == typeof(ObjectOrId<>)) - { - var innerTypeOutput = type.GenericTypeArguments[0]; - - var converterType = typeof(ObjectOrIdConverter<>).MakeGenericType(innerTypeOutput).GetTypeInfo(); - var instanceField = converterType.GetDeclaredField("Instance"); - converter = instanceField.GetValue(null) as JsonConverter; - if (converter == null) - { - var innerConverter = GetConverter(propInfo, innerTypeOutput); - converter = converterType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter; - instanceField.SetValue(null, converter); - } + converter = MakeGenericConverter(propInfo, typeof(OptionalConverter<>), innerTypeOutput); } else converter = GetConverter(propInfo, type); @@ -75,9 +53,18 @@ namespace Discord.Net.Converters return property; } - private JsonConverter GetConverter(MemberInfo member, Type type, TypeInfo typeInfo = null) + private static JsonConverter GetConverter(PropertyInfo propInfo, Type type, TypeInfo typeInfo = null, int depth = 0) { - bool hasInt53 = member.GetCustomAttribute() != null; + if (type.IsArray) + return MakeGenericConverter(propInfo, typeof(ArrayConverter<>), type.GetElementType()); + if (type.IsConstructedGenericType) + { + Type genericType = type.GetGenericTypeDefinition(); + if (genericType == typeof(EntityOrId<>)) + return MakeGenericConverter(propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0]); + } + + bool hasInt53 = propInfo.GetCustomAttribute() != null; //Primitives if (!hasInt53) @@ -100,10 +87,6 @@ namespace Discord.Net.Converters if (typeInfo == null) typeInfo = type.GetTypeInfo(); - //Primitives - if (!hasInt53 && typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEnumerable))) - return UInt64ArrayConverter.Instance; - //Entities if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity))) return UInt64EntityConverter.Instance; @@ -117,5 +100,19 @@ namespace Discord.Net.Converters { return (getter as Func>)((TOwner)owner).IsSpecified; } + + private static JsonConverter MakeGenericConverter(PropertyInfo propInfo, Type converterType, Type innerType) + { + var genericType = converterType.MakeGenericType(innerType).GetTypeInfo(); + var instanceField = genericType.GetDeclaredField("Instance"); + var converter = instanceField.GetValue(null) as JsonConverter; + if (converter == null) + { + var innerConverter = GetConverter(propInfo, innerType); + converter = genericType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter; + instanceField.SetValue(null, converter); + } + return converter; + } } } diff --git a/src/Discord.Net.Core/Net/Converters/ObjectOrIdConverter.cs b/src/Discord.Net.Core/Net/Converters/UInt64EntityOrIdConverter.cs similarity index 61% rename from src/Discord.Net.Core/Net/Converters/ObjectOrIdConverter.cs rename to src/Discord.Net.Core/Net/Converters/UInt64EntityOrIdConverter.cs index 229c8cd87..91644972f 100644 --- a/src/Discord.Net.Core/Net/Converters/ObjectOrIdConverter.cs +++ b/src/Discord.Net.Core/Net/Converters/UInt64EntityOrIdConverter.cs @@ -4,9 +4,9 @@ using System; namespace Discord.Net.Converters { - internal class ObjectOrIdConverter : JsonConverter + internal class UInt64EntityOrIdConverter : JsonConverter { - internal static ObjectOrIdConverter Instance; + public static UInt64EntityOrIdConverter Instance; private readonly JsonConverter _innerConverter; @@ -14,7 +14,7 @@ namespace Discord.Net.Converters public override bool CanRead => true; public override bool CanWrite => false; - public ObjectOrIdConverter(JsonConverter innerConverter) + public UInt64EntityOrIdConverter(JsonConverter innerConverter) { _innerConverter = innerConverter; } @@ -25,9 +25,14 @@ namespace Discord.Net.Converters { case JsonToken.String: case JsonToken.Integer: - return new ObjectOrId(ulong.Parse(reader.ReadAsString())); + return new EntityOrId(ulong.Parse(reader.ReadAsString())); default: - return new ObjectOrId(serializer.Deserialize(reader)); + T obj; + if (_innerConverter != null) + obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer); + else + obj = serializer.Deserialize(reader); + return new EntityOrId(obj); } }