@@ -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;