PageRenderTime 65ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/fastJSON/Reflection.cs

https://bitbucket.org/peterk87/mist
C# | 305 lines | 269 code | 36 blank | 0 comment | 35 complexity | e9bbc74059b3bb94150c67498b4e196f MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Reflection.Emit;
  5. using System.Reflection;
  6. using System.Collections;
  7. namespace fastJSON
  8. {
  9. internal struct Getters
  10. {
  11. public string Name;
  12. public Reflection.GenericGetter Getter;
  13. public Type propertyType;
  14. }
  15. internal sealed class Reflection
  16. {
  17. public readonly static Reflection Instance = new Reflection();
  18. private Reflection()
  19. {
  20. }
  21. public bool ShowReadOnlyProperties = false;
  22. internal delegate object GenericSetter(object target, object value);
  23. internal delegate object GenericGetter(object obj);
  24. private delegate object CreateObject();
  25. private SafeDictionary<Type, string> _tyname = new SafeDictionary<Type, string>();
  26. private SafeDictionary<string, Type> _typecache = new SafeDictionary<string, Type>();
  27. private SafeDictionary<Type, CreateObject> _constrcache = new SafeDictionary<Type, CreateObject>();
  28. private SafeDictionary<Type, List<Getters>> _getterscache = new SafeDictionary<Type, List<Getters>>();
  29. #region [ PROPERTY GET SET ]
  30. internal string GetTypeAssemblyName(Type t)
  31. {
  32. string val = "";
  33. if (_tyname.TryGetValue(t, out val))
  34. return val;
  35. else
  36. {
  37. string s = t.AssemblyQualifiedName;
  38. _tyname.Add(t, s);
  39. return s;
  40. }
  41. }
  42. internal Type GetTypeFromCache(string typename)
  43. {
  44. Type val = null;
  45. if (_typecache.TryGetValue(typename, out val))
  46. return val;
  47. else
  48. {
  49. Type t = Type.GetType(typename);
  50. _typecache.Add(typename, t);
  51. return t;
  52. }
  53. }
  54. internal object FastCreateInstance(Type objtype)
  55. {
  56. try
  57. {
  58. CreateObject c = null;
  59. if (_constrcache.TryGetValue(objtype, out c))
  60. {
  61. return c();
  62. }
  63. else
  64. {
  65. if (objtype.IsClass)
  66. {
  67. DynamicMethod dynMethod = new DynamicMethod("_", objtype, null);
  68. ILGenerator ilGen = dynMethod.GetILGenerator();
  69. ilGen.Emit(OpCodes.Newobj, objtype.GetConstructor(Type.EmptyTypes));
  70. ilGen.Emit(OpCodes.Ret);
  71. c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject));
  72. _constrcache.Add(objtype, c);
  73. }
  74. else // structs
  75. {
  76. DynamicMethod dynMethod = new DynamicMethod("_", typeof(object), null);
  77. ILGenerator ilGen = dynMethod.GetILGenerator();
  78. var lv = ilGen.DeclareLocal(objtype);
  79. ilGen.Emit(OpCodes.Ldloca_S, lv);
  80. ilGen.Emit(OpCodes.Initobj, objtype);
  81. ilGen.Emit(OpCodes.Ldloc_0);
  82. ilGen.Emit(OpCodes.Box, objtype);
  83. ilGen.Emit(OpCodes.Ret);
  84. c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject));
  85. _constrcache.Add(objtype, c);
  86. }
  87. return c();
  88. }
  89. }
  90. catch (Exception exc)
  91. {
  92. throw new Exception(string.Format("Failed to fast create instance for type '{0}' from assemebly '{1}'",
  93. objtype.FullName, objtype.AssemblyQualifiedName), exc);
  94. }
  95. }
  96. internal static GenericSetter CreateSetField(Type type, FieldInfo fieldInfo)
  97. {
  98. Type[] arguments = new Type[2];
  99. arguments[0] = arguments[1] = typeof(object);
  100. DynamicMethod dynamicSet = new DynamicMethod("_", typeof(object), arguments, type);
  101. ILGenerator il = dynamicSet.GetILGenerator();
  102. if (!type.IsClass) // structs
  103. {
  104. var lv = il.DeclareLocal(type);
  105. il.Emit(OpCodes.Ldarg_0);
  106. il.Emit(OpCodes.Unbox_Any, type);
  107. il.Emit(OpCodes.Stloc_0);
  108. il.Emit(OpCodes.Ldloca_S, lv);
  109. il.Emit(OpCodes.Ldarg_1);
  110. if (fieldInfo.FieldType.IsClass)
  111. il.Emit(OpCodes.Castclass, fieldInfo.FieldType);
  112. else
  113. il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
  114. il.Emit(OpCodes.Stfld, fieldInfo);
  115. il.Emit(OpCodes.Ldloc_0);
  116. il.Emit(OpCodes.Box, type);
  117. il.Emit(OpCodes.Ret);
  118. }
  119. else
  120. {
  121. il.Emit(OpCodes.Ldarg_0);
  122. il.Emit(OpCodes.Ldarg_1);
  123. if (fieldInfo.FieldType.IsValueType)
  124. il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
  125. il.Emit(OpCodes.Stfld, fieldInfo);
  126. il.Emit(OpCodes.Ldarg_0);
  127. il.Emit(OpCodes.Ret);
  128. }
  129. return (GenericSetter)dynamicSet.CreateDelegate(typeof(GenericSetter));
  130. }
  131. internal static GenericSetter CreateSetMethod(Type type, PropertyInfo propertyInfo)
  132. {
  133. MethodInfo setMethod = propertyInfo.GetSetMethod();
  134. if (setMethod == null)
  135. return null;
  136. Type[] arguments = new Type[2];
  137. arguments[0] = arguments[1] = typeof(object);
  138. DynamicMethod setter = new DynamicMethod("_", typeof(object), arguments);
  139. ILGenerator il = setter.GetILGenerator();
  140. if (!type.IsClass) // structs
  141. {
  142. var lv = il.DeclareLocal(type);
  143. il.Emit(OpCodes.Ldarg_0);
  144. il.Emit(OpCodes.Unbox_Any, type);
  145. il.Emit(OpCodes.Stloc_0);
  146. il.Emit(OpCodes.Ldloca_S, lv);
  147. il.Emit(OpCodes.Ldarg_1);
  148. if (propertyInfo.PropertyType.IsClass)
  149. il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
  150. else
  151. il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
  152. il.EmitCall(OpCodes.Call, setMethod, null);
  153. il.Emit(OpCodes.Ldloc_0);
  154. il.Emit(OpCodes.Box, type);
  155. }
  156. else
  157. {
  158. il.Emit(OpCodes.Ldarg_0);
  159. il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
  160. il.Emit(OpCodes.Ldarg_1);
  161. if (propertyInfo.PropertyType.IsClass)
  162. il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
  163. else
  164. il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
  165. il.EmitCall(OpCodes.Callvirt, setMethod, null);
  166. il.Emit(OpCodes.Ldarg_0);
  167. }
  168. il.Emit(OpCodes.Ret);
  169. return (GenericSetter)setter.CreateDelegate(typeof(GenericSetter));
  170. }
  171. internal static GenericGetter CreateGetField(Type type, FieldInfo fieldInfo)
  172. {
  173. DynamicMethod dynamicGet = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type);
  174. ILGenerator il = dynamicGet.GetILGenerator();
  175. if (!type.IsClass) // structs
  176. {
  177. var lv = il.DeclareLocal(type);
  178. il.Emit(OpCodes.Ldarg_0);
  179. il.Emit(OpCodes.Unbox_Any, type);
  180. il.Emit(OpCodes.Stloc_0);
  181. il.Emit(OpCodes.Ldloca_S, lv);
  182. il.Emit(OpCodes.Ldfld, fieldInfo);
  183. if (fieldInfo.FieldType.IsValueType)
  184. il.Emit(OpCodes.Box, fieldInfo.FieldType);
  185. }
  186. else
  187. {
  188. il.Emit(OpCodes.Ldarg_0);
  189. il.Emit(OpCodes.Ldfld, fieldInfo);
  190. if (fieldInfo.FieldType.IsValueType)
  191. il.Emit(OpCodes.Box, fieldInfo.FieldType);
  192. }
  193. il.Emit(OpCodes.Ret);
  194. return (GenericGetter)dynamicGet.CreateDelegate(typeof(GenericGetter));
  195. }
  196. internal static GenericGetter CreateGetMethod(Type type, PropertyInfo propertyInfo)
  197. {
  198. MethodInfo getMethod = propertyInfo.GetGetMethod();
  199. if (getMethod == null)
  200. return null;
  201. DynamicMethod getter = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type);
  202. ILGenerator il = getter.GetILGenerator();
  203. if (!type.IsClass) // structs
  204. {
  205. var lv = il.DeclareLocal(type);
  206. il.Emit(OpCodes.Ldarg_0);
  207. il.Emit(OpCodes.Unbox_Any, type);
  208. il.Emit(OpCodes.Stloc_0);
  209. il.Emit(OpCodes.Ldloca_S, lv);
  210. il.EmitCall(OpCodes.Call, getMethod, null);
  211. if (propertyInfo.PropertyType.IsValueType)
  212. il.Emit(OpCodes.Box, propertyInfo.PropertyType);
  213. }
  214. else
  215. {
  216. il.Emit(OpCodes.Ldarg_0);
  217. il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
  218. il.EmitCall(OpCodes.Callvirt, getMethod, null);
  219. if (propertyInfo.PropertyType.IsValueType)
  220. il.Emit(OpCodes.Box, propertyInfo.PropertyType);
  221. }
  222. il.Emit(OpCodes.Ret);
  223. return (GenericGetter)getter.CreateDelegate(typeof(GenericGetter));
  224. }
  225. internal List<Getters> GetGetters(Type type)
  226. {
  227. List<Getters> val = null;
  228. if (_getterscache.TryGetValue(type, out val))
  229. return val;
  230. PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
  231. List<Getters> getters = new List<Getters>();
  232. foreach (PropertyInfo p in props)
  233. {
  234. if (!p.CanWrite && ShowReadOnlyProperties == false) continue;
  235. object[] att = p.GetCustomAttributes(typeof(System.Xml.Serialization.XmlIgnoreAttribute), false);
  236. if (att != null && att.Length > 0)
  237. continue;
  238. GenericGetter g = CreateGetMethod(type, p);
  239. if (g != null)
  240. {
  241. Getters gg = new Getters();
  242. gg.Name = p.Name;
  243. gg.Getter = g;
  244. gg.propertyType = p.PropertyType;
  245. getters.Add(gg);
  246. }
  247. }
  248. FieldInfo[] fi = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
  249. foreach (var f in fi)
  250. {
  251. object[] att = f.GetCustomAttributes(typeof(System.Xml.Serialization.XmlIgnoreAttribute), false);
  252. if (att != null && att.Length > 0)
  253. continue;
  254. GenericGetter g = CreateGetField(type, f);
  255. if (g != null)
  256. {
  257. Getters gg = new Getters();
  258. gg.Name = f.Name;
  259. gg.Getter = g;
  260. gg.propertyType = f.FieldType;
  261. getters.Add(gg);
  262. }
  263. }
  264. _getterscache.Add(type, getters);
  265. return getters;
  266. }
  267. #endregion
  268. }
  269. }