UniVRM/Assets/VRM/UniJSON/Scripts/FormatterExtensionsSerializer.cs

175 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace UniJSON
{
public static class FormatterExtensionsSerializer
{
public static void SerializeDictionary(this IFormatter f, IDictionary<string, object> dictionary)
{
f.BeginMap(dictionary.Count);
foreach (var kv in dictionary)
{
f.Key(kv.Key);
f.SerializeObject(kv.Value);
}
f.EndMap();
}
public static void SerializeArray<T>(this IFormatter f, IEnumerable<T> values)
{
f.BeginList(values.Count());
foreach (var value in values)
{
f.Serialize(value);
}
f.EndList();
}
public static void SerializeObjectArray(this IFormatter f, object[] array)
{
f.BeginList(array.Length);
foreach (var x in array)
{
f.SerializeObject(x);
}
f.EndList();
}
public static void SerializeObject(this IFormatter f, object value)
{
if (value == null)
{
f.Null();
}
else
{
typeof(FormatterExtensionsSerializer).GetMethod("Serialize")
.MakeGenericMethod(value.GetType()).Invoke(null, new object[] { f, value });
}
}
public static void Serialize<T>(this IFormatter f, T arg)
{
if (arg == null)
{
f.Null();
return;
}
GenericSerializer<T>.Serialize(f, arg);
}
public static void SetCustomSerializer<T>(Action<IFormatter, T> serializer)
{
GenericSerializer<T>.Set(serializer);
}
public static MethodInfo GetMethod(string name)
{
return typeof(FormatterExtensionsSerializer).GetMethod(name);
}
}
static class GenericSerializer<T>
{
delegate void Serializer(IFormatter f, T t);
static Action<IFormatter, T> GetSerializer(Type t)
{
// object
if (typeof(T) == typeof(object) && t.GetType() != typeof(object))
{
var mi = FormatterExtensionsSerializer.GetMethod("SerializeObject");
return GenericInvokeCallFactory.CreateAction<IFormatter, T>(mi);
}
try
{
// primitive
var mi = typeof(IFormatter).GetMethod("Value", new Type[] { t });
if (mi != null)
{
return GenericInvokeCallFactory.CreateAction<IFormatter, T>(mi);
}
}
catch (AmbiguousMatchException)
{
// do nothing
}
{
// dictionary
var idictionary = t.GetInterfaces().FirstOrDefault(x =>
x.IsGenericType
&& x.GetGenericTypeDefinition() == typeof(IDictionary<,>)
&& x.GetGenericArguments()[0] == typeof(string)
);
if (idictionary != null)
{
var mi = FormatterExtensionsSerializer.GetMethod("SerializeDictionary");
return GenericInvokeCallFactory.CreateAction<IFormatter, T>(mi);
}
}
{
// object[]
if (t == typeof(object[]))
{
var mi = FormatterExtensionsSerializer.GetMethod("SerializeObjectArray");
return GenericInvokeCallFactory.CreateAction<IFormatter, T>(mi);
}
}
{
// list
var ienumerable = t.GetInterfaces().FirstOrDefault(x =>
x.IsGenericType
&& x.GetGenericTypeDefinition() == typeof(IEnumerable<>)
);
if (ienumerable != null)
{
var g = FormatterExtensionsSerializer.GetMethod("SerializeArray");
var mi = g.MakeGenericMethod(ienumerable.GetGenericArguments());
return GenericInvokeCallFactory.CreateAction<IFormatter, T>(mi);
}
}
{
// reflection
var schema = JsonSchema.FromType<T>();
return (IFormatter f, T value) =>
{
var c = new JsonSchemaValidationContext(value)
{
EnableDiagnosisForNotRequiredFields = true
};
schema.Serialize(f, value, c);
};
}
//throw new NotImplementedException();
}
static Serializer s_serializer;
public static void Set(Action<IFormatter, T> serializer)
{
s_serializer = new Serializer(serializer);
}
public static void Serialize(IFormatter f, T t)
{
if (s_serializer == null)
{
s_serializer = new Serializer(GetSerializer(typeof(T)));
}
s_serializer(f, t);
}
}
}