Browse Source

Added NullableConverter, fixed Image serialization

tags/1.0-rc
RogueException 8 years ago
parent
commit
3ddc59c386
3 changed files with 77 additions and 74 deletions
  1. +27
    -42
      src/Discord.Net.Core/Net/Converters/DiscordContractResolver.cs
  2. +50
    -0
      src/Discord.Net.Core/Net/Converters/NullableConverter.cs
  3. +0
    -32
      src/Discord.Net.Core/Net/Converters/NullableUInt64Converter.cs

+ 27
- 42
src/Discord.Net.Core/Net/Converters/DiscordContractResolver.cs View File

@@ -22,26 +22,7 @@ namespace Discord.Net.Converters
var propInfo = member as PropertyInfo;
if (propInfo != null)
{
JsonConverter converter;
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);

var converter = GetConverter(property, propInfo, propInfo.PropertyType, 0);
if (converter != null)
{
property.Converter = converter;
@@ -53,26 +34,38 @@ namespace Discord.Net.Converters
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)
return MakeGenericConverter(propInfo, typeof(ArrayConverter<>), type.GetElementType());
return MakeGenericConverter(property, propInfo, typeof(ArrayConverter<>), type.GetElementType(), depth);
if (type.IsConstructedGenericType)
{
Type genericType = type.GetGenericTypeDefinition();
if (genericType == typeof(EntityOrId<>))
return MakeGenericConverter(propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0]);
}
if (depth == 0 && genericType == typeof(Optional<>))
{
var typeInput = propInfo.DeclaringType;
var innerTypeOutput = type.GenericTypeArguments[0];

bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null;
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);
}

//Primitives
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null;
if (!hasInt53)
{
if (type == typeof(ulong))
return UInt64Converter.Instance;
if (type == typeof(ulong?))
return NullableUInt64Converter.Instance;
}

//Enums
@@ -82,12 +75,11 @@ namespace Discord.Net.Converters
return UserStatusConverter.Instance;

//Special
if (type == typeof(Image))
return ImageConverter.Instance;

if (typeInfo == null) typeInfo = type.GetTypeInfo();
if (type == typeof(API.Image))
return ImageConverter.Instance;

//Entities
var typeInfo = type.GetTypeInfo();
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>)))
return UInt64EntityConverter.Instance;
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;
}

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 instanceField = genericType.GetDeclaredField("Instance");
//var converter = instanceField.GetValue(null) 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;
var innerConverter = GetConverter(property, propInfo, innerType, depth + 1);
return genericType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter;
}
}
}

+ 50
- 0
src/Discord.Net.Core/Net/Converters/NullableConverter.cs View 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));
}
}
}
}

+ 0
- 32
src/Discord.Net.Core/Net/Converters/NullableUInt64Converter.cs View File

@@ -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();
}
}
}

Loading…
Cancel
Save