Separate GenericDeserializer.cs

This commit is contained in:
ousttrue 2019-02-06 20:03:35 +09:00
parent ba466ff916
commit 0cb031d0ba
3 changed files with 206 additions and 186 deletions

View File

@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace UniJSON
{
public static class GenericDeserializer<T, U>
where T : IListTreeItem, IValue<T>
{
static V[] GenericArrayDeserializer<V>(ListTreeNode<T> s)
{
if (!s.IsArray())
{
throw new ArgumentException("not array: " + s.Value.ValueType);
}
var u = new V[s.GetArrayCount()];
int i = 0;
foreach (var x in s.ArrayItems())
{
x.Deserialize(ref u[i++]);
}
return u;
}
static List<V> GenericListDeserializer<V>(ListTreeNode<T> s)
{
if (!s.IsArray())
{
throw new ArgumentException("not array: " + s.Value.ValueType);
}
var u = new List<V>(s.GetArrayCount());
foreach (var x in s.ArrayItems())
{
var e = default(V);
x.Deserialize(ref e);
u.Add(e);
}
return u;
}
delegate void FieldSetter(ListTreeNode<T> s, object o);
static FieldSetter GetFieldDeserializer<V>(FieldInfo fi)
{
return (s, o) =>
{
var u = default(V);
s.Deserialize(ref u);
fi.SetValue(o, u);
};
}
static Func<ListTreeNode<T>, U> GetDeserializer()
{
// primitive
{
var mi = typeof(ListTreeNode<T>).GetMethods().FirstOrDefault(x =>
{
if (!x.Name.StartsWith("Get"))
{
return false;
}
if (!x.Name.EndsWith(typeof(U).Name))
{
return false;
}
var parameters = x.GetParameters();
if (parameters.Length != 0)
{
return false;
}
if (x.ReturnType != typeof(U))
{
return false;
}
return true;
});
if (mi != null)
{
return GenericInvokeCallFactory.StaticFunc<ListTreeNode<T>, U>(mi);
}
}
var target = typeof(U);
if (target.IsArray)
{
var mi = typeof(GenericDeserializer<T, U>).GetMethod("GenericArrayDeserializer",
BindingFlags.Static | BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(target.GetElementType());
return GenericInvokeCallFactory.StaticFunc<ListTreeNode<T>, U>(g);
}
if (target.IsGenericType)
{
if (target.GetGenericTypeDefinition() == typeof(List<>))
{
var mi = typeof(GenericDeserializer<T, U>).GetMethod("GenericListDeserializer",
BindingFlags.Static | BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(target.GetGenericArguments());
return GenericInvokeCallFactory.StaticFunc<ListTreeNode<T>, U>(g);
}
if (target.GetGenericTypeDefinition() == typeof(Dictionary<,>) &&
target.GetGenericArguments()[0] == typeof(string))
{
var mi = typeof(ListTreeNodeDeserializerExtensions).GetMethod("DictionaryDeserializer",
BindingFlags.Static | BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(typeof(T));
return GenericInvokeCallFactory.StaticFunc<ListTreeNode<T>, U>(g);
}
}
{
var schema = JsonSchema.FromType<U>();
return s =>
{
var t = default(U);
schema.Validator.Deserialize(s, ref t);
return t;
};
}
#if false
if (target.IsEnum)
{
var value = Expression.Parameter(typeof(int), "value");
var cast = Expression.Convert(value, target);
var func = Expression.Lambda(cast, value);
var compiled = (Func<int, T>)func.Compile();
return s =>
{
return compiled(s.GetInt32());
};
}
{
var fields = target.GetFields(BindingFlags.Instance | BindingFlags.Public);
var fieldDeserializers = fields.ToDictionary(x => Utf8String.From(x.Name), x =>
{
var mi = typeof(GenericDeserializer<S, T>).GetMethod("GetFieldDeserializer",
BindingFlags.Static|BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(x.FieldType);
return (FieldSetter)g.Invoke(null, new object[] { x });
});
return (S s) =>
{
if (!s.IsMap())
{
throw new ArgumentException(s.ValueType.ToString());
}
var t = (object)default(GenericCreator<S, T>).Create(s);
foreach(var kv in s.ObjectItems())
{
FieldSetter setter;
if (fieldDeserializers.TryGetValue(kv.Key, out setter))
{
setter(kv.Value, t);
}
}
return (T)t;
};
}
#endif
}
public delegate U Deserializer(ListTreeNode<T> node);
public static Deserializer s_deserializer;
public static void Deserialize(ListTreeNode<T> node, ref U value)
{
if (s_deserializer == null)
{
var d = GetDeserializer();
s_deserializer = new Deserializer(d);
}
value = s_deserializer(node);
}
public static void SetCustomDeserializer(Deserializer deserializer)
{
s_deserializer = deserializer;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 74625bf2a3d6bc64d9d92b08221a8a3d
timeCreated: 1549450914
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -51,190 +51,4 @@ namespace UniJSON
GenericDeserializer<T, U>.Deserialize(self, ref value);
}
}
public static class GenericDeserializer<T, U>
where T : IListTreeItem, IValue<T>
{
static V[] GenericArrayDeserializer<V>(ListTreeNode<T> s)
{
if (!s.IsArray())
{
throw new ArgumentException("not array: " + s.Value.ValueType);
}
var u = new V[s.GetArrayCount()];
int i = 0;
foreach (var x in s.ArrayItems())
{
x.Deserialize(ref u[i++]);
}
return u;
}
static List<V> GenericListDeserializer<V>(ListTreeNode<T> s)
{
if (!s.IsArray())
{
throw new ArgumentException("not array: " + s.Value.ValueType);
}
var u = new List<V>(s.GetArrayCount());
foreach (var x in s.ArrayItems())
{
var e = default(V);
x.Deserialize(ref e);
u.Add(e);
}
return u;
}
delegate void FieldSetter(ListTreeNode<T> s, object o);
static FieldSetter GetFieldDeserializer<V>(FieldInfo fi)
{
return (s, o) =>
{
var u = default(V);
s.Deserialize(ref u);
fi.SetValue(o, u);
};
}
static Func<ListTreeNode<T>, U> GetDeserializer()
{
// primitive
{
var mi = typeof(ListTreeNode<T>).GetMethods().FirstOrDefault(x =>
{
if (!x.Name.StartsWith("Get"))
{
return false;
}
if (!x.Name.EndsWith(typeof(U).Name))
{
return false;
}
var parameters = x.GetParameters();
if (parameters.Length != 0)
{
return false;
}
if (x.ReturnType != typeof(U))
{
return false;
}
return true;
});
if (mi != null)
{
return GenericInvokeCallFactory.StaticFunc<ListTreeNode<T>, U>(mi);
}
}
var target = typeof(U);
if (target.IsArray)
{
var mi = typeof(GenericDeserializer<T, U>).GetMethod("GenericArrayDeserializer",
BindingFlags.Static | BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(target.GetElementType());
return GenericInvokeCallFactory.StaticFunc<ListTreeNode<T>, U>(g);
}
if (target.IsGenericType)
{
if (target.GetGenericTypeDefinition() == typeof(List<>))
{
var mi = typeof(GenericDeserializer<T, U>).GetMethod("GenericListDeserializer",
BindingFlags.Static | BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(target.GetGenericArguments());
return GenericInvokeCallFactory.StaticFunc<ListTreeNode<T>, U>(g);
}
if (target.GetGenericTypeDefinition() == typeof(Dictionary<,>) &&
target.GetGenericArguments()[0] == typeof(string))
{
var mi = typeof(ListTreeNodeDeserializerExtensions).GetMethod("DictionaryDeserializer",
BindingFlags.Static | BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(typeof(T));
return GenericInvokeCallFactory.StaticFunc<ListTreeNode<T>, U>(g);
}
}
{
var schema = JsonSchema.FromType<U>();
return s =>
{
var t = default(U);
schema.Validator.Deserialize(s, ref t);
return t;
};
}
#if false
if (target.IsEnum)
{
var value = Expression.Parameter(typeof(int), "value");
var cast = Expression.Convert(value, target);
var func = Expression.Lambda(cast, value);
var compiled = (Func<int, T>)func.Compile();
return s =>
{
return compiled(s.GetInt32());
};
}
{
var fields = target.GetFields(BindingFlags.Instance | BindingFlags.Public);
var fieldDeserializers = fields.ToDictionary(x => Utf8String.From(x.Name), x =>
{
var mi = typeof(GenericDeserializer<S, T>).GetMethod("GetFieldDeserializer",
BindingFlags.Static|BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(x.FieldType);
return (FieldSetter)g.Invoke(null, new object[] { x });
});
return (S s) =>
{
if (!s.IsMap())
{
throw new ArgumentException(s.ValueType.ToString());
}
var t = (object)default(GenericCreator<S, T>).Create(s);
foreach(var kv in s.ObjectItems())
{
FieldSetter setter;
if (fieldDeserializers.TryGetValue(kv.Key, out setter))
{
setter(kv.Value, t);
}
}
return (T)t;
};
}
#endif
}
public delegate U Deserializer(ListTreeNode<T> node);
public static Deserializer s_deserializer;
public static void Deserialize(ListTreeNode<T> node, ref U value)
{
if (s_deserializer == null)
{
var d = GetDeserializer();
s_deserializer = new Deserializer(d);
}
value = s_deserializer(node);
}
public static void SetCustomDeserializer(Deserializer deserializer)
{
s_deserializer = deserializer;
}
}
}