using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace UniJSON { public static class GenericDeserializer where T : IListTreeItem, IValue { public static V[] GenericArrayDeserializer(ListTreeNode 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; } public static List GenericListDeserializer(ListTreeNode s) { if (!s.IsArray()) { throw new ArgumentException("not array: " + s.Value.ValueType); } var u = new List(s.GetArrayCount()); foreach (var x in s.ArrayItems()) { var e = default(V); x.Deserialize(ref e); u.Add(e); } return u; } public static object DefaultDictionaryDeserializer(ListTreeNode s) { switch (s.Value.ValueType) { case ValueNodeType.Object: { var u = new Dictionary(); foreach (var kv in s.ObjectItems()) { //var e = default(object); //kv.Value.Deserialize(ref e); u.Add(kv.Key.GetString(), DefaultDictionaryDeserializer(kv.Value)); } return u; } case ValueNodeType.Null: return null; case ValueNodeType.Boolean: return s.GetBoolean(); case ValueNodeType.Integer: return s.GetInt32(); case ValueNodeType.Number: return s.GetDouble(); case ValueNodeType.String: return s.GetString(); default: throw new NotImplementedException(s.Value.ValueType.ToString()); } } /// /// Deserialize Dictionary only string key /// /// /// /// public static Dictionary DictionaryDeserializer(ListTreeNode s) { var d = new Dictionary(); foreach (var kv in s.ObjectItems()) { var value = default(V); GenericDeserializer.Deserialize(kv.Value, ref value); d.Add(kv.Key.GetString(), value); } return d; } delegate void FieldSetter(ListTreeNode s, object o); static FieldSetter GetFieldDeserializer(FieldInfo fi) { return (s, o) => { var u = default(V); s.Deserialize(ref u); fi.SetValue(o, u); }; } static Func, U> GetDeserializer() { // primitive { var mi = typeof(ListTreeNode).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, U>(mi); } } var target = typeof(U); if (target.IsArray) { var mi = typeof(GenericDeserializer).GetMethod("GenericArrayDeserializer", BindingFlags.Static | BindingFlags.Public); var g = mi.MakeGenericMethod(target.GetElementType()); return GenericInvokeCallFactory.StaticFunc, U>(g); } if (target.IsGenericType) { if (target.GetGenericTypeDefinition() == typeof(List<>)) { var mi = typeof(GenericDeserializer).GetMethod("GenericListDeserializer", BindingFlags.Static | BindingFlags.Public); var g = mi.MakeGenericMethod(target.GetGenericArguments()); return GenericInvokeCallFactory.StaticFunc, U>(g); } if (target == typeof(Dictionary)) { var mi = typeof(GenericDeserializer).GetMethod("DefaultDictionaryDeserializer", BindingFlags.Static | BindingFlags.Public); return GenericInvokeCallFactory.StaticFunc, U>(mi); } else if (target.GetGenericTypeDefinition() == typeof(Dictionary<,>) && target.GetGenericArguments()[0] == typeof(string)) { var mi = typeof(GenericDeserializer).GetMethod("DictionaryDeserializer", BindingFlags.Static | BindingFlags.Public); var g = mi.MakeGenericMethod(target.GetGenericArguments()[1]); return GenericInvokeCallFactory.StaticFunc, U>(g); } } { var schema = JsonSchema.FromType(); 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)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).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).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 node); public static Deserializer s_deserializer; public static void Deserialize(ListTreeNode 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; } } }