Reflection.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  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. #if !SILVERLIGHT
  8. using System.Data;
  9. #endif
  10. using System.Collections.Specialized;
  11. namespace FastJSON
  12. {
  13. internal struct Getters
  14. {
  15. public string Name;
  16. public string lcName;
  17. //public string OtherName;
  18. public Reflection.GenericGetter Getter;
  19. }
  20. internal enum myPropInfoType
  21. {
  22. Int,
  23. Long,
  24. String,
  25. Bool,
  26. DateTime,
  27. Enum,
  28. Guid,
  29. Array,
  30. ByteArray,
  31. Dictionary,
  32. StringKeyDictionary,
  33. NameValue,
  34. StringDictionary,
  35. #if !SILVERLIGHT
  36. Hashtable,
  37. DataSet,
  38. DataTable,
  39. #endif
  40. Custom,
  41. Unknown,
  42. }
  43. internal struct myPropInfo
  44. {
  45. public Type pt;
  46. public Type bt;
  47. public Type changeType;
  48. public Reflection.GenericSetter setter;
  49. public Reflection.GenericGetter getter;
  50. public Type[] GenericTypes;
  51. public string Name;
  52. public myPropInfoType Type;
  53. public bool CanWrite;
  54. public bool IsClass;
  55. public bool IsValueType;
  56. public bool IsGenericType;
  57. public bool IsStruct;
  58. }
  59. internal sealed class Reflection
  60. {
  61. // Sinlgeton pattern 4 from : http://csharpindepth.com/articles/general/singleton.aspx
  62. private static readonly Reflection instance = new Reflection();
  63. // Explicit static constructor to tell C# compiler
  64. // not to mark type as beforefieldinit
  65. static Reflection()
  66. {
  67. }
  68. private Reflection()
  69. {
  70. }
  71. public static Reflection Instance { get { return instance; } }
  72. internal delegate object GenericSetter(object target, object value);
  73. internal delegate object GenericGetter(object obj);
  74. private delegate object CreateObject();
  75. private SafeDictionary<Type, string> _tyname = new SafeDictionary<Type, string>();
  76. private SafeDictionary<string, Type> _typecache = new SafeDictionary<string, Type>();
  77. private SafeDictionary<Type, CreateObject> _constrcache = new SafeDictionary<Type, CreateObject>();
  78. private SafeDictionary<Type, Getters[]> _getterscache = new SafeDictionary<Type, Getters[]>();
  79. private SafeDictionary<string, Dictionary<string, myPropInfo>> _propertycache = new SafeDictionary<string, Dictionary<string, myPropInfo>>();
  80. private SafeDictionary<Type, Type[]> _genericTypes = new SafeDictionary<Type, Type[]>();
  81. private SafeDictionary<Type, Type> _genericTypeDef = new SafeDictionary<Type, Type>();
  82. #region json custom types
  83. // JSON custom
  84. internal SafeDictionary<Type, Serialize> _customSerializer = new SafeDictionary<Type, Serialize>();
  85. internal SafeDictionary<Type, Deserialize> _customDeserializer = new SafeDictionary<Type, Deserialize>();
  86. internal object CreateCustom(string v, Type type)
  87. {
  88. Deserialize d;
  89. _customDeserializer.TryGetValue(type, out d);
  90. return d(v);
  91. }
  92. internal void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer)
  93. {
  94. if (type != null && serializer != null && deserializer != null)
  95. {
  96. _customSerializer.Add(type, serializer);
  97. _customDeserializer.Add(type, deserializer);
  98. // reset property cache
  99. Reflection.Instance.ResetPropertyCache();
  100. }
  101. }
  102. internal bool IsTypeRegistered(Type t)
  103. {
  104. if (_customSerializer.Count == 0)
  105. return false;
  106. Serialize s;
  107. return _customSerializer.TryGetValue(t, out s);
  108. }
  109. #endregion
  110. public Type GetGenericTypeDefinition(Type t)
  111. {
  112. Type tt = null;
  113. if (_genericTypeDef.TryGetValue(t, out tt))
  114. return tt;
  115. else
  116. {
  117. tt = t.GetGenericTypeDefinition();
  118. _genericTypeDef.Add(t, tt);
  119. return tt;
  120. }
  121. }
  122. public Type[] GetGenericArguments(Type t)
  123. {
  124. Type[] tt = null;
  125. if (_genericTypes.TryGetValue(t, out tt))
  126. return tt;
  127. else
  128. {
  129. tt = t.GetGenericArguments();
  130. _genericTypes.Add(t, tt);
  131. return tt;
  132. }
  133. }
  134. public Dictionary<string, myPropInfo> Getproperties(Type type, string typename, bool customType)
  135. {
  136. Dictionary<string, myPropInfo> sd = null;
  137. if (_propertycache.TryGetValue(typename, out sd))
  138. {
  139. return sd;
  140. }
  141. else
  142. {
  143. sd = new Dictionary<string, myPropInfo>();
  144. PropertyInfo[] pr = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
  145. foreach (PropertyInfo p in pr)
  146. {
  147. if (p.GetIndexParameters().Length > 0)
  148. {// Property is an indexer
  149. continue;
  150. }
  151. myPropInfo d = CreateMyProp(p.PropertyType, p.Name, customType);
  152. d.setter = Reflection.CreateSetMethod(type, p);
  153. if (d.setter != null)
  154. d.CanWrite = true;
  155. d.getter = Reflection.CreateGetMethod(type, p);
  156. sd.Add(p.Name.ToLower(), d);
  157. }
  158. FieldInfo[] fi = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
  159. foreach (FieldInfo f in fi)
  160. {
  161. myPropInfo d = CreateMyProp(f.FieldType, f.Name, customType);
  162. if (f.IsLiteral == false)
  163. {
  164. d.setter = Reflection.CreateSetField(type, f);
  165. if (d.setter != null)
  166. d.CanWrite = true;
  167. d.getter = Reflection.CreateGetField(type, f);
  168. sd.Add(f.Name.ToLower(), d);
  169. }
  170. }
  171. _propertycache.Add(typename, sd);
  172. return sd;
  173. }
  174. }
  175. private myPropInfo CreateMyProp(Type t, string name, bool customType)
  176. {
  177. myPropInfo d = new myPropInfo();
  178. myPropInfoType d_type = myPropInfoType.Unknown;
  179. if (t == typeof(int) || t == typeof(int?)) d_type = myPropInfoType.Int;
  180. else if (t == typeof(long) || t == typeof(long?)) d_type = myPropInfoType.Long;
  181. else if (t == typeof(string)) d_type = myPropInfoType.String;
  182. else if (t == typeof(bool) || t == typeof(bool?)) d_type = myPropInfoType.Bool;
  183. else if (t == typeof(DateTime) || t == typeof(DateTime?)) d_type = myPropInfoType.DateTime;
  184. else if (t.IsEnum) d_type = myPropInfoType.Enum;
  185. else if (t == typeof(Guid) || t == typeof(Guid?)) d_type = myPropInfoType.Guid;
  186. else if (t == typeof(StringDictionary)) d_type = myPropInfoType.StringDictionary;
  187. else if (t == typeof(NameValueCollection)) d_type = myPropInfoType.NameValue;
  188. else if (t.IsArray)
  189. {
  190. d.bt = t.GetElementType();
  191. if (t == typeof(byte[]))
  192. d_type = myPropInfoType.ByteArray;
  193. else
  194. d_type = myPropInfoType.Array;
  195. }
  196. else if (t.Name.Contains("Dictionary"))
  197. {
  198. d.GenericTypes = Reflection.Instance.GetGenericArguments(t);// t.GetGenericArguments();
  199. if (d.GenericTypes.Length > 0 && d.GenericTypes[0] == typeof(string))
  200. d_type = myPropInfoType.StringKeyDictionary;
  201. else
  202. d_type = myPropInfoType.Dictionary;
  203. }
  204. #if !SILVERLIGHT
  205. else if (t == typeof(Hashtable)) d_type = myPropInfoType.Hashtable;
  206. else if (t == typeof(DataSet)) d_type = myPropInfoType.DataSet;
  207. else if (t == typeof(DataTable)) d_type = myPropInfoType.DataTable;
  208. #endif
  209. else if (customType)
  210. d_type = myPropInfoType.Custom;
  211. if (t.IsValueType && !t.IsPrimitive && !t.IsEnum && t != typeof(decimal))
  212. d.IsStruct = true;
  213. d.IsClass = t.IsClass;
  214. d.IsValueType = t.IsValueType;
  215. if (t.IsGenericType)
  216. {
  217. d.IsGenericType = true;
  218. d.bt = t.GetGenericArguments()[0];
  219. }
  220. d.pt = t;
  221. d.Name = name;
  222. d.changeType = GetChangeType(t);
  223. d.Type = d_type;
  224. return d;
  225. }
  226. private Type GetChangeType(Type conversionType)
  227. {
  228. if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
  229. return Reflection.Instance.GetGenericArguments(conversionType)[0];// conversionType.GetGenericArguments()[0];
  230. return conversionType;
  231. }
  232. #region [ PROPERTY GET SET ]
  233. internal string GetTypeAssemblyName(Type t)
  234. {
  235. string val = "";
  236. if (_tyname.TryGetValue(t, out val))
  237. return val;
  238. else
  239. {
  240. string s = t.AssemblyQualifiedName;
  241. _tyname.Add(t, s);
  242. return s;
  243. }
  244. }
  245. internal Type GetTypeFromCache(string typename)
  246. {
  247. Type val = null;
  248. if (_typecache.TryGetValue(typename, out val))
  249. return val;
  250. else
  251. {
  252. Type t = Type.GetType(typename);
  253. //if (t == null) // RaptorDB : loading runtime assemblies
  254. //{
  255. // t = Type.GetType(typename, (name) => {
  256. // return AppDomain.CurrentDomain.GetAssemblies().Where(z => z.FullName == name.FullName).FirstOrDefault();
  257. // }, null, true);
  258. //}
  259. _typecache.Add(typename, t);
  260. return t;
  261. }
  262. }
  263. internal object FastCreateInstance(Type objtype)
  264. {
  265. try
  266. {
  267. CreateObject c = null;
  268. if (_constrcache.TryGetValue(objtype, out c))
  269. {
  270. return c();
  271. }
  272. else
  273. {
  274. if (objtype.IsClass)
  275. {
  276. DynamicMethod dynMethod = new DynamicMethod("_", objtype, null);
  277. ILGenerator ilGen = dynMethod.GetILGenerator();
  278. ilGen.Emit(OpCodes.Newobj, objtype.GetConstructor(Type.EmptyTypes));
  279. ilGen.Emit(OpCodes.Ret);
  280. c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject));
  281. _constrcache.Add(objtype, c);
  282. }
  283. else // structs
  284. {
  285. DynamicMethod dynMethod = new DynamicMethod("_", typeof(object), null);
  286. ILGenerator ilGen = dynMethod.GetILGenerator();
  287. var lv = ilGen.DeclareLocal(objtype);
  288. ilGen.Emit(OpCodes.Ldloca_S, lv);
  289. ilGen.Emit(OpCodes.Initobj, objtype);
  290. ilGen.Emit(OpCodes.Ldloc_0);
  291. ilGen.Emit(OpCodes.Box, objtype);
  292. ilGen.Emit(OpCodes.Ret);
  293. c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject));
  294. _constrcache.Add(objtype, c);
  295. }
  296. return c();
  297. }
  298. }
  299. catch (Exception exc)
  300. {
  301. throw new Exception(string.Format("Failed to fast create instance for type '{0}' from assembly '{1}'",
  302. objtype.FullName, objtype.AssemblyQualifiedName), exc);
  303. }
  304. }
  305. internal static GenericSetter CreateSetField(Type type, FieldInfo fieldInfo)
  306. {
  307. Type[] arguments = new Type[2];
  308. arguments[0] = arguments[1] = typeof(object);
  309. DynamicMethod dynamicSet = new DynamicMethod("_", typeof(object), arguments, type);
  310. ILGenerator il = dynamicSet.GetILGenerator();
  311. if (!type.IsClass) // structs
  312. {
  313. var lv = il.DeclareLocal(type);
  314. il.Emit(OpCodes.Ldarg_0);
  315. il.Emit(OpCodes.Unbox_Any, type);
  316. il.Emit(OpCodes.Stloc_0);
  317. il.Emit(OpCodes.Ldloca_S, lv);
  318. il.Emit(OpCodes.Ldarg_1);
  319. if (fieldInfo.FieldType.IsClass)
  320. il.Emit(OpCodes.Castclass, fieldInfo.FieldType);
  321. else
  322. il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
  323. il.Emit(OpCodes.Stfld, fieldInfo);
  324. il.Emit(OpCodes.Ldloc_0);
  325. il.Emit(OpCodes.Box, type);
  326. il.Emit(OpCodes.Ret);
  327. }
  328. else
  329. {
  330. il.Emit(OpCodes.Ldarg_0);
  331. il.Emit(OpCodes.Ldarg_1);
  332. if (fieldInfo.FieldType.IsValueType)
  333. il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
  334. il.Emit(OpCodes.Stfld, fieldInfo);
  335. il.Emit(OpCodes.Ldarg_0);
  336. il.Emit(OpCodes.Ret);
  337. }
  338. return (GenericSetter)dynamicSet.CreateDelegate(typeof(GenericSetter));
  339. }
  340. internal static GenericSetter CreateSetMethod(Type type, PropertyInfo propertyInfo)
  341. {
  342. MethodInfo setMethod = propertyInfo.GetSetMethod();
  343. if (setMethod == null)
  344. return null;
  345. Type[] arguments = new Type[2];
  346. arguments[0] = arguments[1] = typeof(object);
  347. DynamicMethod setter = new DynamicMethod("_", typeof(object), arguments);
  348. ILGenerator il = setter.GetILGenerator();
  349. if (!type.IsClass) // structs
  350. {
  351. var lv = il.DeclareLocal(type);
  352. il.Emit(OpCodes.Ldarg_0);
  353. il.Emit(OpCodes.Unbox_Any, type);
  354. il.Emit(OpCodes.Stloc_0);
  355. il.Emit(OpCodes.Ldloca_S, lv);
  356. il.Emit(OpCodes.Ldarg_1);
  357. if (propertyInfo.PropertyType.IsClass)
  358. il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
  359. else
  360. il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
  361. il.EmitCall(OpCodes.Call, setMethod, null);
  362. il.Emit(OpCodes.Ldloc_0);
  363. il.Emit(OpCodes.Box, type);
  364. }
  365. else
  366. {
  367. if (!setMethod.IsStatic)
  368. {
  369. il.Emit(OpCodes.Ldarg_0);
  370. il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
  371. il.Emit(OpCodes.Ldarg_1);
  372. if (propertyInfo.PropertyType.IsClass)
  373. il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
  374. else
  375. il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
  376. il.EmitCall(OpCodes.Callvirt, setMethod, null);
  377. il.Emit(OpCodes.Ldarg_0);
  378. }
  379. else
  380. {
  381. il.Emit(OpCodes.Ldarg_0);
  382. il.Emit(OpCodes.Ldarg_1);
  383. if (propertyInfo.PropertyType.IsClass)
  384. il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
  385. else
  386. il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
  387. il.Emit(OpCodes.Call, setMethod);
  388. }
  389. }
  390. il.Emit(OpCodes.Ret);
  391. return (GenericSetter)setter.CreateDelegate(typeof(GenericSetter));
  392. }
  393. internal static GenericGetter CreateGetField(Type type, FieldInfo fieldInfo)
  394. {
  395. DynamicMethod dynamicGet = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type);
  396. ILGenerator il = dynamicGet.GetILGenerator();
  397. if (!type.IsClass) // structs
  398. {
  399. var lv = il.DeclareLocal(type);
  400. il.Emit(OpCodes.Ldarg_0);
  401. il.Emit(OpCodes.Unbox_Any, type);
  402. il.Emit(OpCodes.Stloc_0);
  403. il.Emit(OpCodes.Ldloca_S, lv);
  404. il.Emit(OpCodes.Ldfld, fieldInfo);
  405. if (fieldInfo.FieldType.IsValueType)
  406. il.Emit(OpCodes.Box, fieldInfo.FieldType);
  407. }
  408. else
  409. {
  410. il.Emit(OpCodes.Ldarg_0);
  411. il.Emit(OpCodes.Ldfld, fieldInfo);
  412. if (fieldInfo.FieldType.IsValueType)
  413. il.Emit(OpCodes.Box, fieldInfo.FieldType);
  414. }
  415. il.Emit(OpCodes.Ret);
  416. return (GenericGetter)dynamicGet.CreateDelegate(typeof(GenericGetter));
  417. }
  418. internal static GenericGetter CreateGetMethod(Type type, PropertyInfo propertyInfo)
  419. {
  420. MethodInfo getMethod = propertyInfo.GetGetMethod();
  421. if (getMethod == null)
  422. return null;
  423. DynamicMethod getter = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type);
  424. ILGenerator il = getter.GetILGenerator();
  425. if (!type.IsClass) // structs
  426. {
  427. var lv = il.DeclareLocal(type);
  428. il.Emit(OpCodes.Ldarg_0);
  429. il.Emit(OpCodes.Unbox_Any, type);
  430. il.Emit(OpCodes.Stloc_0);
  431. il.Emit(OpCodes.Ldloca_S, lv);
  432. il.EmitCall(OpCodes.Call, getMethod, null);
  433. if (propertyInfo.PropertyType.IsValueType)
  434. il.Emit(OpCodes.Box, propertyInfo.PropertyType);
  435. }
  436. else
  437. {
  438. if (!getMethod.IsStatic)
  439. {
  440. il.Emit(OpCodes.Ldarg_0);
  441. il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
  442. il.EmitCall(OpCodes.Callvirt, getMethod, null);
  443. }
  444. else
  445. il.Emit(OpCodes.Call, getMethod);
  446. if (propertyInfo.PropertyType.IsValueType)
  447. il.Emit(OpCodes.Box, propertyInfo.PropertyType);
  448. }
  449. il.Emit(OpCodes.Ret);
  450. return (GenericGetter)getter.CreateDelegate(typeof(GenericGetter));
  451. }
  452. internal Getters[] GetGetters(Type type, bool ShowReadOnlyProperties, List<Type> IgnoreAttributes)//JSONParameters param)
  453. {
  454. Getters[] val = null;
  455. if (_getterscache.TryGetValue(type, out val))
  456. return val;
  457. PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
  458. List<Getters> getters = new List<Getters>();
  459. foreach (PropertyInfo p in props)
  460. {
  461. if (p.GetIndexParameters().Length > 0)
  462. {// Property is an indexer
  463. continue;
  464. }
  465. if (!p.CanWrite && ShowReadOnlyProperties == false) continue;
  466. if (IgnoreAttributes != null)
  467. {
  468. bool found = false;
  469. foreach (var ignoreAttr in IgnoreAttributes)
  470. {
  471. if (p.IsDefined(ignoreAttr, false))
  472. {
  473. found = true;
  474. break;
  475. }
  476. }
  477. if (found)
  478. continue;
  479. }
  480. GenericGetter g = CreateGetMethod(type, p);
  481. if (g != null)
  482. getters.Add(new Getters { Getter = g, Name = p.Name, lcName = p.Name.ToLower() });
  483. }
  484. FieldInfo[] fi = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
  485. foreach (var f in fi)
  486. {
  487. if (IgnoreAttributes != null)
  488. {
  489. bool found = false;
  490. foreach (var ignoreAttr in IgnoreAttributes)
  491. {
  492. if (f.IsDefined(ignoreAttr, false))
  493. {
  494. found = true;
  495. break;
  496. }
  497. }
  498. if (found)
  499. continue;
  500. }
  501. if (f.IsLiteral == false)
  502. {
  503. GenericGetter g = CreateGetField(type, f);
  504. if (g != null)
  505. getters.Add(new Getters { Getter = g, Name = f.Name, lcName = f.Name.ToLower() });
  506. }
  507. }
  508. val = getters.ToArray();
  509. _getterscache.Add(type, val);
  510. return val;
  511. }
  512. #endregion
  513. internal void ResetPropertyCache()
  514. {
  515. _propertycache = new SafeDictionary<string, Dictionary<string, myPropInfo>>();
  516. }
  517. internal void ClearReflectionCache()
  518. {
  519. _tyname = new SafeDictionary<Type, string>();
  520. _typecache = new SafeDictionary<string, Type>();
  521. _constrcache = new SafeDictionary<Type, CreateObject>();
  522. _getterscache = new SafeDictionary<Type, Getters[]>();
  523. _propertycache = new SafeDictionary<string, Dictionary<string, myPropInfo>>();
  524. _genericTypes = new SafeDictionary<Type, Type[]>();
  525. _genericTypeDef = new SafeDictionary<Type, Type>();
  526. }
  527. }
  528. }