123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612 |
- using System;
- using System.Collections.Generic;
- using System.Reflection.Emit;
- using System.Reflection;
- using System.Collections;
- using System.Text;
- #if !SILVERLIGHT
- using System.Data;
- #endif
- using System.Collections.Specialized;
- namespace fastJSON
- {
- internal struct Getters
- {
- public string Name;
- public string lcName;
- 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;
- public bool IsInterface;
- }
- 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<Type, string> _tyname = new SafeDictionary<Type, string>();
- private SafeDictionary<string, Type> _typecache = new SafeDictionary<string, Type>();
- private SafeDictionary<Type, CreateObject> _constrcache = new SafeDictionary<Type, CreateObject>();
- private SafeDictionary<Type, Getters[]> _getterscache = new SafeDictionary<Type, Getters[]>();
- private SafeDictionary<string, Dictionary<string, myPropInfo>> _propertycache = new SafeDictionary<string, Dictionary<string, myPropInfo>>();
- private SafeDictionary<Type, Type[]> _genericTypes = new SafeDictionary<Type, Type[]>();
- private SafeDictionary<Type, Type> _genericTypeDef = new SafeDictionary<Type, Type>();
- #region bjson custom types
- internal UnicodeEncoding unicode = new UnicodeEncoding();
- internal UTF8Encoding utf8 = new UTF8Encoding();
- #endregion
- #region json custom types
- // JSON custom
- internal SafeDictionary<Type, Serialize> _customSerializer = new SafeDictionary<Type, Serialize>();
- internal SafeDictionary<Type, Deserialize> _customDeserializer = new SafeDictionary<Type, Deserialize>();
- 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
- 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<string, myPropInfo> Getproperties(Type type, string typename)
- {
- Dictionary<string, myPropInfo> sd = null;
- if (_propertycache.TryGetValue(typename, out sd))
- {
- return sd;
- }
- else
- {
- sd = new Dictionary<string, myPropInfo>();
- var bf = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
- PropertyInfo[] pr = type.GetProperties(bf);
- foreach (PropertyInfo p in pr)
- {
- if (p.GetIndexParameters().Length > 0)// Property is an indexer
- continue;
- myPropInfo d = CreateMyProp(p.PropertyType, p.Name);
- 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(bf);
- foreach (FieldInfo f in fi)
- {
- myPropInfo d = CreateMyProp(f.FieldType, f.Name);
- 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)
- {
- 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);
- 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 (IsTypeRegistered(t))
- d_type = myPropInfoType.Custom;
- if (t.IsValueType && !t.IsPrimitive && !t.IsEnum && t != typeof(decimal))
- d.IsStruct = true;
- d.IsInterface = t.IsInterface;
- 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];
- 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<Type> IgnoreAttributes)
- {
- Getters[] val = null;
- if (_getterscache.TryGetValue(type, out val))
- return val;
- //bool isAnonymous = IsAnonymousType(type);
- var bf = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
- //if (ShowReadOnlyProperties)
- // bf |= BindingFlags.NonPublic;
- PropertyInfo[] props = type.GetProperties(bf);
- List<Getters> getters = new List<Getters>();
- foreach (PropertyInfo p in props)
- {
- if (p.GetIndexParameters().Length > 0)
- {// Property is an indexer
- continue;
- }
- if (!p.CanWrite && (ShowReadOnlyProperties == false))//|| isAnonymous == 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(bf);
- 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;
- }
- //private static bool IsAnonymousType(Type type)
- //{
- // // may break in the future if compiler defined names change...
- // const string CS_ANONYMOUS_PREFIX = "<>f__AnonymousType";
- // const string VB_ANONYMOUS_PREFIX = "VB$AnonymousType";
- // if (type == null)
- // throw new ArgumentNullException("type");
- // if (type.Name.StartsWith(CS_ANONYMOUS_PREFIX, StringComparison.Ordinal) || type.Name.StartsWith(VB_ANONYMOUS_PREFIX, StringComparison.Ordinal))
- // {
- // return type.IsDefined(typeof(CompilerGeneratedAttribute), false);
- // }
- // return false;
- //}
- #endregion
- internal void ResetPropertyCache()
- {
- _propertycache = new SafeDictionary<string, Dictionary<string, myPropInfo>>();
- }
- internal void ClearReflectionCache()
- {
- _tyname = new SafeDictionary<Type, string>();
- _typecache = new SafeDictionary<string, Type>();
- _constrcache = new SafeDictionary<Type, CreateObject>();
- _getterscache = new SafeDictionary<Type, Getters[]>();
- _propertycache = new SafeDictionary<string, Dictionary<string, myPropInfo>>();
- _genericTypes = new SafeDictionary<Type, Type[]>();
- _genericTypeDef = new SafeDictionary<Type, Type>();
- }
- }
- }
|