Reflection.cs 8.2 KB

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