using System; using System.Collections.Generic; using System.Text; using System.Reflection.Emit; using System.Reflection; using System.Collections; #if !SILVERLIGHT using System.Data; #endif using System.Collections.Specialized; namespace FastJSON { internal struct Getters { public string Name; public string lcName; //public string OtherName; public Reflection.GenericGetter Getter; } internal enum myPropInfoType { Int, Long, String, Bool, DateTime, Enum, Guid, Array, ByteArray, Dictionary, StringKeyDictionary, NameValue, StringDictionary, #if !SILVERLIGHT Hashtable, DataSet, DataTable, #endif Custom, Unknown, } internal struct myPropInfo { public Type pt; public Type bt; public Type changeType; public Reflection.GenericSetter setter; public Reflection.GenericGetter getter; public Type[] GenericTypes; public string Name; public myPropInfoType Type; public bool CanWrite; public bool IsClass; public bool IsValueType; public bool IsGenericType; public bool IsStruct; } internal sealed class Reflection { // Sinlgeton pattern 4 from : http://csharpindepth.com/articles/general/singleton.aspx private static readonly Reflection instance = new Reflection(); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Reflection() { } private Reflection() { } public static Reflection Instance { get { return instance; } } internal delegate object GenericSetter(object target, object value); internal delegate object GenericGetter(object obj); private delegate object CreateObject(); private SafeDictionary _tyname = new SafeDictionary(); private SafeDictionary _typecache = new SafeDictionary(); private SafeDictionary _constrcache = new SafeDictionary(); private SafeDictionary _getterscache = new SafeDictionary(); private SafeDictionary> _propertycache = new SafeDictionary>(); private SafeDictionary _genericTypes = new SafeDictionary(); private SafeDictionary _genericTypeDef = new SafeDictionary(); #region json custom types // JSON custom internal SafeDictionary _customSerializer = new SafeDictionary(); internal SafeDictionary _customDeserializer = new SafeDictionary(); internal object CreateCustom(string v, Type type) { Deserialize d; _customDeserializer.TryGetValue(type, out d); return d(v); } internal void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer) { if (type != null && serializer != null && deserializer != null) { _customSerializer.Add(type, serializer); _customDeserializer.Add(type, deserializer); // reset property cache Reflection.Instance.ResetPropertyCache(); } } internal bool IsTypeRegistered(Type t) { if (_customSerializer.Count == 0) return false; Serialize s; return _customSerializer.TryGetValue(t, out s); } #endregion public Type GetGenericTypeDefinition(Type t) { Type tt = null; if (_genericTypeDef.TryGetValue(t, out tt)) return tt; else { tt = t.GetGenericTypeDefinition(); _genericTypeDef.Add(t, tt); return tt; } } public Type[] GetGenericArguments(Type t) { Type[] tt = null; if (_genericTypes.TryGetValue(t, out tt)) return tt; else { tt = t.GetGenericArguments(); _genericTypes.Add(t, tt); return tt; } } public Dictionary Getproperties(Type type, string typename, bool customType) { Dictionary sd = null; if (_propertycache.TryGetValue(typename, out sd)) { return sd; } else { sd = new Dictionary(); PropertyInfo[] pr = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (PropertyInfo p in pr) { if (p.GetIndexParameters().Length > 0) {// Property is an indexer continue; } myPropInfo d = CreateMyProp(p.PropertyType, p.Name, customType); d.setter = Reflection.CreateSetMethod(type, p); if (d.setter != null) d.CanWrite = true; d.getter = Reflection.CreateGetMethod(type, p); sd.Add(p.Name.ToLower(), d); } FieldInfo[] fi = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (FieldInfo f in fi) { myPropInfo d = CreateMyProp(f.FieldType, f.Name, customType); if (f.IsLiteral == false) { d.setter = Reflection.CreateSetField(type, f); if (d.setter != null) d.CanWrite = true; d.getter = Reflection.CreateGetField(type, f); sd.Add(f.Name.ToLower(), d); } } _propertycache.Add(typename, sd); return sd; } } private myPropInfo CreateMyProp(Type t, string name, bool customType) { myPropInfo d = new myPropInfo(); myPropInfoType d_type = myPropInfoType.Unknown; if (t == typeof(int) || t == typeof(int?)) d_type = myPropInfoType.Int; else if (t == typeof(long) || t == typeof(long?)) d_type = myPropInfoType.Long; else if (t == typeof(string)) d_type = myPropInfoType.String; else if (t == typeof(bool) || t == typeof(bool?)) d_type = myPropInfoType.Bool; else if (t == typeof(DateTime) || t == typeof(DateTime?)) d_type = myPropInfoType.DateTime; else if (t.IsEnum) d_type = myPropInfoType.Enum; else if (t == typeof(Guid) || t == typeof(Guid?)) d_type = myPropInfoType.Guid; else if (t == typeof(StringDictionary)) d_type = myPropInfoType.StringDictionary; else if (t == typeof(NameValueCollection)) d_type = myPropInfoType.NameValue; else if (t.IsArray) { d.bt = t.GetElementType(); if (t == typeof(byte[])) d_type = myPropInfoType.ByteArray; else d_type = myPropInfoType.Array; } else if (t.Name.Contains("Dictionary")) { d.GenericTypes = Reflection.Instance.GetGenericArguments(t);// t.GetGenericArguments(); if (d.GenericTypes.Length > 0 && d.GenericTypes[0] == typeof(string)) d_type = myPropInfoType.StringKeyDictionary; else d_type = myPropInfoType.Dictionary; } #if !SILVERLIGHT else if (t == typeof(Hashtable)) d_type = myPropInfoType.Hashtable; else if (t == typeof(DataSet)) d_type = myPropInfoType.DataSet; else if (t == typeof(DataTable)) d_type = myPropInfoType.DataTable; #endif else if (customType) d_type = myPropInfoType.Custom; if (t.IsValueType && !t.IsPrimitive && !t.IsEnum && t != typeof(decimal)) d.IsStruct = true; d.IsClass = t.IsClass; d.IsValueType = t.IsValueType; if (t.IsGenericType) { d.IsGenericType = true; d.bt = t.GetGenericArguments()[0]; } d.pt = t; d.Name = name; d.changeType = GetChangeType(t); d.Type = d_type; return d; } private Type GetChangeType(Type conversionType) { if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) return Reflection.Instance.GetGenericArguments(conversionType)[0];// conversionType.GetGenericArguments()[0]; return conversionType; } #region [ PROPERTY GET SET ] internal string GetTypeAssemblyName(Type t) { string val = ""; if (_tyname.TryGetValue(t, out val)) return val; else { string s = t.AssemblyQualifiedName; _tyname.Add(t, s); return s; } } internal Type GetTypeFromCache(string typename) { Type val = null; if (_typecache.TryGetValue(typename, out val)) return val; else { Type t = Type.GetType(typename); //if (t == null) // RaptorDB : loading runtime assemblies //{ // t = Type.GetType(typename, (name) => { // return AppDomain.CurrentDomain.GetAssemblies().Where(z => z.FullName == name.FullName).FirstOrDefault(); // }, null, true); //} _typecache.Add(typename, t); return t; } } internal object FastCreateInstance(Type objtype) { try { CreateObject c = null; if (_constrcache.TryGetValue(objtype, out c)) { return c(); } else { if (objtype.IsClass) { DynamicMethod dynMethod = new DynamicMethod("_", objtype, null); ILGenerator ilGen = dynMethod.GetILGenerator(); ilGen.Emit(OpCodes.Newobj, objtype.GetConstructor(Type.EmptyTypes)); ilGen.Emit(OpCodes.Ret); c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject)); _constrcache.Add(objtype, c); } else // structs { DynamicMethod dynMethod = new DynamicMethod("_", typeof(object), null); ILGenerator ilGen = dynMethod.GetILGenerator(); var lv = ilGen.DeclareLocal(objtype); ilGen.Emit(OpCodes.Ldloca_S, lv); ilGen.Emit(OpCodes.Initobj, objtype); ilGen.Emit(OpCodes.Ldloc_0); ilGen.Emit(OpCodes.Box, objtype); ilGen.Emit(OpCodes.Ret); c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject)); _constrcache.Add(objtype, c); } return c(); } } catch (Exception exc) { throw new Exception(string.Format("Failed to fast create instance for type '{0}' from assembly '{1}'", objtype.FullName, objtype.AssemblyQualifiedName), exc); } } internal static GenericSetter CreateSetField(Type type, FieldInfo fieldInfo) { Type[] arguments = new Type[2]; arguments[0] = arguments[1] = typeof(object); DynamicMethod dynamicSet = new DynamicMethod("_", typeof(object), arguments, type); ILGenerator il = dynamicSet.GetILGenerator(); if (!type.IsClass) // structs { var lv = il.DeclareLocal(type); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Unbox_Any, type); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloca_S, lv); il.Emit(OpCodes.Ldarg_1); if (fieldInfo.FieldType.IsClass) il.Emit(OpCodes.Castclass, fieldInfo.FieldType); else il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType); il.Emit(OpCodes.Stfld, fieldInfo); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Ret); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); if (fieldInfo.FieldType.IsValueType) il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType); il.Emit(OpCodes.Stfld, fieldInfo); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ret); } return (GenericSetter)dynamicSet.CreateDelegate(typeof(GenericSetter)); } internal static GenericSetter CreateSetMethod(Type type, PropertyInfo propertyInfo) { MethodInfo setMethod = propertyInfo.GetSetMethod(); if (setMethod == null) return null; Type[] arguments = new Type[2]; arguments[0] = arguments[1] = typeof(object); DynamicMethod setter = new DynamicMethod("_", typeof(object), arguments); ILGenerator il = setter.GetILGenerator(); if (!type.IsClass) // structs { var lv = il.DeclareLocal(type); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Unbox_Any, type); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloca_S, lv); il.Emit(OpCodes.Ldarg_1); if (propertyInfo.PropertyType.IsClass) il.Emit(OpCodes.Castclass, propertyInfo.PropertyType); else il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); il.EmitCall(OpCodes.Call, setMethod, null); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Box, type); } else { if (!setMethod.IsStatic) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); il.Emit(OpCodes.Ldarg_1); if (propertyInfo.PropertyType.IsClass) il.Emit(OpCodes.Castclass, propertyInfo.PropertyType); else il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); il.EmitCall(OpCodes.Callvirt, setMethod, null); il.Emit(OpCodes.Ldarg_0); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); if (propertyInfo.PropertyType.IsClass) il.Emit(OpCodes.Castclass, propertyInfo.PropertyType); else il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); il.Emit(OpCodes.Call, setMethod); } } il.Emit(OpCodes.Ret); return (GenericSetter)setter.CreateDelegate(typeof(GenericSetter)); } internal static GenericGetter CreateGetField(Type type, FieldInfo fieldInfo) { DynamicMethod dynamicGet = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type); ILGenerator il = dynamicGet.GetILGenerator(); if (!type.IsClass) // structs { var lv = il.DeclareLocal(type); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Unbox_Any, type); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloca_S, lv); il.Emit(OpCodes.Ldfld, fieldInfo); if (fieldInfo.FieldType.IsValueType) il.Emit(OpCodes.Box, fieldInfo.FieldType); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, fieldInfo); if (fieldInfo.FieldType.IsValueType) il.Emit(OpCodes.Box, fieldInfo.FieldType); } il.Emit(OpCodes.Ret); return (GenericGetter)dynamicGet.CreateDelegate(typeof(GenericGetter)); } internal static GenericGetter CreateGetMethod(Type type, PropertyInfo propertyInfo) { MethodInfo getMethod = propertyInfo.GetGetMethod(); if (getMethod == null) return null; DynamicMethod getter = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type); ILGenerator il = getter.GetILGenerator(); if (!type.IsClass) // structs { var lv = il.DeclareLocal(type); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Unbox_Any, type); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloca_S, lv); il.EmitCall(OpCodes.Call, getMethod, null); if (propertyInfo.PropertyType.IsValueType) il.Emit(OpCodes.Box, propertyInfo.PropertyType); } else { if (!getMethod.IsStatic) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); il.EmitCall(OpCodes.Callvirt, getMethod, null); } else il.Emit(OpCodes.Call, getMethod); if (propertyInfo.PropertyType.IsValueType) il.Emit(OpCodes.Box, propertyInfo.PropertyType); } il.Emit(OpCodes.Ret); return (GenericGetter)getter.CreateDelegate(typeof(GenericGetter)); } internal Getters[] GetGetters(Type type, bool ShowReadOnlyProperties, List IgnoreAttributes)//JSONParameters param) { Getters[] val = null; if (_getterscache.TryGetValue(type, out val)) return val; PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); List getters = new List(); foreach (PropertyInfo p in props) { if (p.GetIndexParameters().Length > 0) {// Property is an indexer continue; } if (!p.CanWrite && ShowReadOnlyProperties == false) continue; if (IgnoreAttributes != null) { bool found = false; foreach (var ignoreAttr in IgnoreAttributes) { if (p.IsDefined(ignoreAttr, false)) { found = true; break; } } if (found) continue; } GenericGetter g = CreateGetMethod(type, p); if (g != null) getters.Add(new Getters { Getter = g, Name = p.Name, lcName = p.Name.ToLower() }); } FieldInfo[] fi = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static); foreach (var f in fi) { if (IgnoreAttributes != null) { bool found = false; foreach (var ignoreAttr in IgnoreAttributes) { if (f.IsDefined(ignoreAttr, false)) { found = true; break; } } if (found) continue; } if (f.IsLiteral == false) { GenericGetter g = CreateGetField(type, f); if (g != null) getters.Add(new Getters { Getter = g, Name = f.Name, lcName = f.Name.ToLower() }); } } val = getters.ToArray(); _getterscache.Add(type, val); return val; } #endregion internal void ResetPropertyCache() { _propertycache = new SafeDictionary>(); } internal void ClearReflectionCache() { _tyname = new SafeDictionary(); _typecache = new SafeDictionary(); _constrcache = new SafeDictionary(); _getterscache = new SafeDictionary(); _propertycache = new SafeDictionary>(); _genericTypes = new SafeDictionary(); _genericTypeDef = new SafeDictionary(); } } }