|
|
@@ -3,6 +3,7 @@ using Newtonsoft.Json; |
|
|
|
using Newtonsoft.Json.Serialization; |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.IO; |
|
|
|
using System.Linq; |
|
|
|
using System.Reflection; |
|
|
|
|
|
|
@@ -17,59 +18,34 @@ namespace Discord.Net.Converters |
|
|
|
{ |
|
|
|
var property = base.CreateProperty(member, memberSerialization); |
|
|
|
var propInfo = member as PropertyInfo; |
|
|
|
|
|
|
|
if (propInfo != null) |
|
|
|
{ |
|
|
|
JsonConverter converter = null; |
|
|
|
var type = property.PropertyType; |
|
|
|
var typeInfo = type.GetTypeInfo(); |
|
|
|
JsonConverter converter; |
|
|
|
var type = propInfo.PropertyType; |
|
|
|
|
|
|
|
//Primitives |
|
|
|
if (propInfo.GetCustomAttribute<Int53Attribute>() == null) |
|
|
|
if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Optional<>)) |
|
|
|
{ |
|
|
|
if (type == typeof(ulong)) |
|
|
|
converter = UInt64Converter.Instance; |
|
|
|
else if (type == typeof(ulong?)) |
|
|
|
converter = NullableUInt64Converter.Instance; |
|
|
|
else if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEnumerable<ulong>))) |
|
|
|
converter = UInt64ArrayConverter.Instance; |
|
|
|
} |
|
|
|
if (converter == null) |
|
|
|
{ |
|
|
|
//Enums |
|
|
|
if (type == typeof(ChannelType)) |
|
|
|
converter = ChannelTypeConverter.Instance; |
|
|
|
else if (type == typeof(PermissionTarget)) |
|
|
|
converter = PermissionTargetConverter.Instance; |
|
|
|
else if (type == typeof(UserStatus)) |
|
|
|
converter = UserStatusConverter.Instance; |
|
|
|
else if (type == typeof(Direction)) |
|
|
|
converter = DirectionConverter.Instance; |
|
|
|
var typeInput = propInfo.DeclaringType; |
|
|
|
var innerTypeOutput = type.GenericTypeArguments[0]; |
|
|
|
|
|
|
|
//Entities |
|
|
|
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>))) |
|
|
|
converter = UInt64EntityConverter.Instance; |
|
|
|
else if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<string>))) |
|
|
|
converter = StringEntityConverter.Instance; |
|
|
|
var getter = typeof(Func<,>).MakeGenericType(typeInput, type); |
|
|
|
var getterDelegate = propInfo.GetMethod.CreateDelegate(getter); |
|
|
|
var shouldSerialize = _shouldSerialize.MakeGenericMethod(typeInput, innerTypeOutput); |
|
|
|
var shouldSerializeDelegate = (Func<object, Delegate, bool>)shouldSerialize.CreateDelegate(typeof(Func<object, Delegate, bool>)); |
|
|
|
property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate); |
|
|
|
|
|
|
|
//Special |
|
|
|
else if (type == typeof(string) && propInfo.GetCustomAttribute<ImageAttribute>() != null) |
|
|
|
converter = ImageConverter.Instance; |
|
|
|
else if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Optional<>)) |
|
|
|
var converterType = typeof(OptionalConverter<>).MakeGenericType(innerTypeOutput).GetTypeInfo(); |
|
|
|
var instanceField = converterType.GetDeclaredField("Instance"); |
|
|
|
converter = instanceField.GetValue(null) as JsonConverter; |
|
|
|
if (converter == null) |
|
|
|
{ |
|
|
|
var typeInput = propInfo.DeclaringType; |
|
|
|
var innerTypeOutput = type.GenericTypeArguments[0]; |
|
|
|
|
|
|
|
var getter = typeof(Func<,>).MakeGenericType(typeInput, type); |
|
|
|
var getterDelegate = propInfo.GetMethod.CreateDelegate(getter); |
|
|
|
var shouldSerialize = _shouldSerialize.MakeGenericMethod(typeInput, innerTypeOutput); |
|
|
|
var shouldSerializeDelegate = (Func<object, Delegate, bool>)shouldSerialize.CreateDelegate(typeof(Func<object, Delegate, bool>)); |
|
|
|
property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate); |
|
|
|
|
|
|
|
var converterType = typeof(OptionalConverter<>).MakeGenericType(innerTypeOutput); |
|
|
|
converter = converterType.GetTypeInfo().GetDeclaredField("Instance").GetValue(null) as JsonConverter; |
|
|
|
var innerConverter = GetConverter(propInfo, innerTypeOutput); |
|
|
|
converter = converterType.DeclaredConstructors.FirstOrDefault().Invoke(new object[] { innerConverter }) as JsonConverter; |
|
|
|
instanceField.SetValue(null, converter); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
converter = GetConverter(propInfo, type); |
|
|
|
|
|
|
|
if (converter != null) |
|
|
|
{ |
|
|
@@ -77,10 +53,52 @@ namespace Discord.Net.Converters |
|
|
|
property.MemberConverter = converter; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return property; |
|
|
|
} |
|
|
|
|
|
|
|
private JsonConverter GetConverter(PropertyInfo propInfo, Type type, TypeInfo typeInfo = null) |
|
|
|
{ |
|
|
|
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null; |
|
|
|
|
|
|
|
//Primitives |
|
|
|
if (!hasInt53) |
|
|
|
{ |
|
|
|
if (type == typeof(ulong)) |
|
|
|
return UInt64Converter.Instance; |
|
|
|
if (type == typeof(ulong?)) |
|
|
|
return NullableUInt64Converter.Instance; |
|
|
|
} |
|
|
|
|
|
|
|
//Enums |
|
|
|
if (type == typeof(ChannelType)) |
|
|
|
return ChannelTypeConverter.Instance; |
|
|
|
if (type == typeof(PermissionTarget)) |
|
|
|
return PermissionTargetConverter.Instance; |
|
|
|
if (type == typeof(UserStatus)) |
|
|
|
return UserStatusConverter.Instance; |
|
|
|
if (type == typeof(Direction)) |
|
|
|
return DirectionConverter.Instance; |
|
|
|
|
|
|
|
//Special |
|
|
|
if (type == typeof(Stream) && propInfo.GetCustomAttribute<ImageAttribute>() != null) |
|
|
|
return ImageConverter.Instance; |
|
|
|
|
|
|
|
|
|
|
|
if (typeInfo == null) typeInfo = type.GetTypeInfo(); |
|
|
|
|
|
|
|
//Primitives |
|
|
|
if (!hasInt53 && typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEnumerable<ulong>))) |
|
|
|
return UInt64ArrayConverter.Instance; |
|
|
|
|
|
|
|
//Entities |
|
|
|
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>))) |
|
|
|
return UInt64EntityConverter.Instance; |
|
|
|
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<string>))) |
|
|
|
return StringEntityConverter.Instance; |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
private static bool ShouldSerialize<TOwner, TValue>(object owner, Delegate getter) |
|
|
|
{ |
|
|
|
return (getter as Func<TOwner, Optional<TValue>>)((TOwner)owner).IsSpecified; |
|
|
|