Added NullableConverter, fixed Image serialization
This commit is contained in:
@@ -22,26 +22,7 @@ namespace Discord.Net.Converters
|
|||||||
var propInfo = member as PropertyInfo;
|
var propInfo = member as PropertyInfo;
|
||||||
if (propInfo != null)
|
if (propInfo != null)
|
||||||
{
|
{
|
||||||
JsonConverter converter;
|
var converter = GetConverter(property, propInfo, propInfo.PropertyType, 0);
|
||||||
Type type = propInfo.PropertyType;
|
|
||||||
Type genericType = type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : null;
|
|
||||||
|
|
||||||
if (genericType == typeof(Optional<>))
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
converter = MakeGenericConverter(propInfo, typeof(OptionalConverter<>), innerTypeOutput);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
converter = GetConverter(propInfo, type);
|
|
||||||
|
|
||||||
if (converter != null)
|
if (converter != null)
|
||||||
{
|
{
|
||||||
property.Converter = converter;
|
property.Converter = converter;
|
||||||
@@ -53,26 +34,38 @@ namespace Discord.Net.Converters
|
|||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JsonConverter GetConverter(PropertyInfo propInfo, Type type, TypeInfo typeInfo = null, int depth = 0)
|
private static JsonConverter GetConverter(JsonProperty property, PropertyInfo propInfo, Type type, int depth)
|
||||||
{
|
{
|
||||||
if (type.IsArray)
|
if (type.IsArray)
|
||||||
return MakeGenericConverter(propInfo, typeof(ArrayConverter<>), type.GetElementType());
|
return MakeGenericConverter(property, propInfo, typeof(ArrayConverter<>), type.GetElementType(), depth);
|
||||||
if (type.IsConstructedGenericType)
|
if (type.IsConstructedGenericType)
|
||||||
{
|
{
|
||||||
Type genericType = type.GetGenericTypeDefinition();
|
Type genericType = type.GetGenericTypeDefinition();
|
||||||
if (genericType == typeof(EntityOrId<>))
|
if (depth == 0 && genericType == typeof(Optional<>))
|
||||||
return MakeGenericConverter(propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0]);
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
return MakeGenericConverter(property, propInfo, typeof(OptionalConverter<>), innerTypeOutput, depth);
|
||||||
|
}
|
||||||
|
else if (genericType == typeof(Nullable<>))
|
||||||
|
return MakeGenericConverter(property, propInfo, typeof(NullableConverter<>), type.GenericTypeArguments[0], depth);
|
||||||
|
else if (genericType == typeof(EntityOrId<>))
|
||||||
|
return MakeGenericConverter(property, propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0], depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null;
|
|
||||||
|
|
||||||
//Primitives
|
//Primitives
|
||||||
|
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null;
|
||||||
if (!hasInt53)
|
if (!hasInt53)
|
||||||
{
|
{
|
||||||
if (type == typeof(ulong))
|
if (type == typeof(ulong))
|
||||||
return UInt64Converter.Instance;
|
return UInt64Converter.Instance;
|
||||||
if (type == typeof(ulong?))
|
|
||||||
return NullableUInt64Converter.Instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Enums
|
//Enums
|
||||||
@@ -82,12 +75,11 @@ namespace Discord.Net.Converters
|
|||||||
return UserStatusConverter.Instance;
|
return UserStatusConverter.Instance;
|
||||||
|
|
||||||
//Special
|
//Special
|
||||||
if (type == typeof(Image))
|
if (type == typeof(API.Image))
|
||||||
return ImageConverter.Instance;
|
return ImageConverter.Instance;
|
||||||
|
|
||||||
if (typeInfo == null) typeInfo = type.GetTypeInfo();
|
|
||||||
|
|
||||||
//Entities
|
//Entities
|
||||||
|
var typeInfo = type.GetTypeInfo();
|
||||||
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>)))
|
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>)))
|
||||||
return UInt64EntityConverter.Instance;
|
return UInt64EntityConverter.Instance;
|
||||||
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<string>)))
|
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<string>)))
|
||||||
@@ -101,18 +93,11 @@ namespace Discord.Net.Converters
|
|||||||
return (getter as Func<TOwner, Optional<TValue>>)((TOwner)owner).IsSpecified;
|
return (getter as Func<TOwner, Optional<TValue>>)((TOwner)owner).IsSpecified;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JsonConverter MakeGenericConverter(PropertyInfo propInfo, Type converterType, Type innerType)
|
private static JsonConverter MakeGenericConverter(JsonProperty property, PropertyInfo propInfo, Type converterType, Type innerType, int depth)
|
||||||
{
|
{
|
||||||
var genericType = converterType.MakeGenericType(innerType).GetTypeInfo();
|
var genericType = converterType.MakeGenericType(innerType).GetTypeInfo();
|
||||||
//var instanceField = genericType.GetDeclaredField("Instance");
|
var innerConverter = GetConverter(property, propInfo, innerType, depth + 1);
|
||||||
//var converter = instanceField.GetValue(null) as JsonConverter;
|
return genericType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter;
|
||||||
//if (converter == null)
|
|
||||||
//{
|
|
||||||
var innerConverter = GetConverter(propInfo, innerType);
|
|
||||||
var converter = genericType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter;
|
|
||||||
//instanceField.SetValue(null, converter);
|
|
||||||
//}
|
|
||||||
return converter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
50
src/Discord.Net.Core/Net/Converters/NullableConverter.cs
Normal file
50
src/Discord.Net.Core/Net/Converters/NullableConverter.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Discord.Net.Converters
|
||||||
|
{
|
||||||
|
internal class NullableConverter<T> : JsonConverter
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
private readonly JsonConverter _innerConverter;
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType) => true;
|
||||||
|
public override bool CanRead => true;
|
||||||
|
public override bool CanWrite => true;
|
||||||
|
|
||||||
|
public NullableConverter(JsonConverter innerConverter)
|
||||||
|
{
|
||||||
|
_innerConverter = innerConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
object value = reader.Value;
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T obj;
|
||||||
|
if (_innerConverter != null)
|
||||||
|
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer);
|
||||||
|
else
|
||||||
|
obj = serializer.Deserialize<T>(reader);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
writer.WriteNull();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var nullable = (T?)value;
|
||||||
|
if (_innerConverter != null)
|
||||||
|
_innerConverter.WriteJson(writer, nullable.Value, serializer);
|
||||||
|
else
|
||||||
|
serializer.Serialize(writer, nullable.Value, typeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
namespace Discord.Net.Converters
|
|
||||||
{
|
|
||||||
internal class NullableUInt64Converter : JsonConverter
|
|
||||||
{
|
|
||||||
public static readonly NullableUInt64Converter Instance = new NullableUInt64Converter();
|
|
||||||
|
|
||||||
public override bool CanConvert(Type objectType) => true;
|
|
||||||
public override bool CanRead => true;
|
|
||||||
public override bool CanWrite => true;
|
|
||||||
|
|
||||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
object value = reader.Value;
|
|
||||||
if (value != null)
|
|
||||||
return ulong.Parse(value.ToString(), NumberStyles.None, CultureInfo.InvariantCulture);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
if (value != null)
|
|
||||||
writer.WriteValue(((ulong?)value).Value.ToString(CultureInfo.InvariantCulture));
|
|
||||||
else
|
|
||||||
writer.WriteNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user