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 dictionary) { f.BeginMap(dictionary.Count); foreach (var kv in dictionary) { f.Key(kv.Key); f.SerializeObject(kv.Value); } f.EndMap(); } public static void SerializeArray(this IFormatter f, IEnumerable 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(this IFormatter f, T arg) { if (arg == null) { f.Null(); return; } GenericSerializer.Serialize(f, arg); } public static void SetCustomSerializer(Action serializer) { GenericSerializer.Set(serializer); } public static MethodInfo GetMethod(string name) { return typeof(FormatterExtensionsSerializer).GetMethod(name); } } static class GenericSerializer { delegate void Serializer(IFormatter f, T t); static Action GetSerializer() { var t = typeof(T); // object if (typeof(T) == typeof(object) && t.GetType() != typeof(object)) { var mi = FormatterExtensionsSerializer.GetMethod("SerializeObject"); return GenericInvokeCallFactory.StaticAction(mi); } try { // primitive var mi = typeof(IFormatter).GetMethod("Value", new Type[] { t }); if (mi != null) { return GenericInvokeCallFactory.OpenAction(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.StaticAction(mi); } } { // object[] if (t == typeof(object[])) { var mi = FormatterExtensionsSerializer.GetMethod("SerializeObjectArray"); return GenericInvokeCallFactory.StaticAction(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.StaticAction(mi); } } throw new NotImplementedException(); } static Serializer s_serializer; public static void Set(Action serializer) { s_serializer = new Serializer(serializer); } public static void Serialize(IFormatter f, T t) { if (s_serializer == null) { s_serializer = new Serializer(GetSerializer()); } s_serializer(f, t); } } }