PageRenderTime 56ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Reflection/ReflectionHelper.cs

http://github.com/fredericaltorres/DynamicSugarNet
C# | 499 lines | 309 code | 53 blank | 137 comment | 49 complexity | 5dfa4dccd07178785d77cf71053efce2 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Reflection;
  6. namespace DynamicSugar {
  7. public class ParameterMetadata {
  8. public bool IsIn;
  9. public bool IsOptional;
  10. public bool IsOut;
  11. public bool IsRetval;
  12. public string Name;
  13. public Type ParameterType;
  14. public int Position;
  15. public object RawDefaultValue;
  16. public object Value;
  17. public ParameterMetadata(ParameterInfo pi, object value){
  18. this.IsIn = pi.IsIn;
  19. this.IsOptional = pi.IsOptional;
  20. this.IsOut = pi.IsOut;
  21. this.IsRetval = pi.IsRetval;
  22. this.Name = pi.Name;
  23. this.ParameterType = pi.ParameterType;
  24. this.Position = pi.Position;
  25. this.RawDefaultValue = pi.RawDefaultValue;
  26. this.Value = value;
  27. }
  28. }
  29. /// <summary>
  30. ///
  31. /// </summary>
  32. public class ReflectionHelper {
  33. const BindingFlags GET_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.GetProperty;
  34. const BindingFlags GET_FLAGS_STATIC = BindingFlags.Static | BindingFlags.Public | BindingFlags.GetField | BindingFlags.GetProperty;
  35. const BindingFlags CALL_METHOD_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod;
  36. const BindingFlags CALL_STATIC_METHOD_FLAGS = BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod;
  37. public static string GetStackCall() {
  38. try {
  39. System.Reflection.MethodBase method = null;
  40. var b = new StringBuilder();
  41. int i = 1;
  42. int max = (new System.Diagnostics.StackTrace(true)).FrameCount;
  43. while (i < max) {
  44. method = new System.Diagnostics.StackTrace(true).GetFrame(i).GetMethod();
  45. if (method == null)
  46. break;
  47. else {
  48. if (
  49. (method.Name.ToLower() != "trace") &&
  50. (method.Name.ToLower() != "trace_error") &&
  51. (method.Name.ToLower() != "trace_method")
  52. ) {
  53. b.AppendFormat("{1}.{0} -> ", method.Name, method.ReflectedType.FullName);
  54. }
  55. }
  56. i++;
  57. }
  58. return b.ToString();
  59. }
  60. catch {
  61. return null;
  62. }
  63. }
  64. public static System.Reflection.MethodBase GetCallingMethod(params string[] methodToIgnore) {
  65. return GetCallingMethod(methodToIgnore.ToList());
  66. }
  67. public static System.Reflection.MethodBase GetCallingMethod(List<string> methodToIgnore = null) {
  68. try {
  69. if(methodToIgnore==null)
  70. methodToIgnore = new List<string>();
  71. methodToIgnore.Add("GetCallingMethod");// Alway ignore the current method
  72. MethodBase method = null;
  73. int i = 1;
  74. int max = (new System.Diagnostics.StackTrace(true)).FrameCount;
  75. while (i <= max) {
  76. method = new System.Diagnostics.StackTrace(true).GetFrame(i).GetMethod();
  77. if(!method.Name.In(methodToIgnore))
  78. break;
  79. i++;
  80. }
  81. return method;
  82. }
  83. catch {
  84. return null;
  85. }
  86. }
  87. /// <summary>
  88. /// Create new instance of the type
  89. /// </summary>
  90. /// <param name="typeToInstantiate"></param>
  91. /// <param name="parameters"></param>
  92. /// <returns></returns>
  93. public static object Constructor(Type typeToInstantiate, params object[] parameters) {
  94. object o = Activator.CreateInstance(typeToInstantiate, parameters);
  95. return o;
  96. }
  97. /// <summary>
  98. /// Create new instance of the type with casting in the right type
  99. /// </summary>
  100. /// <typeparam name="T"></typeparam>
  101. /// <param name="typeToInstantiate"></param>
  102. /// <param name="parameters"></param>
  103. /// <returns></returns>
  104. public static T Constructor<T>(Type typeToInstantiate, params object[] parameters) {
  105. object o = Activator.CreateInstance(typeToInstantiate, parameters);
  106. T t = (T)Convert.ChangeType(o, typeof(T));
  107. return t;
  108. }
  109. /// <summary>
  110. ///
  111. /// </summary>
  112. /// <param name="parameterValues"></param>
  113. /// <returns></returns>
  114. public static Dictionary<string, Object> GetLocals(params object[] parameterValues){
  115. var dic = new Dictionary<string,Object>();
  116. var m = GetCallingMethod("GetLocals");
  117. var i = 0;
  118. foreach(var mp in m.GetParameters())
  119. dic.Add(mp.Name, parameterValues[i++]);
  120. return dic;
  121. }
  122. /// <summary>
  123. ///
  124. /// </summary>
  125. /// <param name="parameterValues"></param>
  126. /// <returns></returns>
  127. public static Dictionary<string, ParameterMetadata> GetLocalsEx(params object[] parameterValues){
  128. Dictionary<string, ParameterMetadata> dic = new Dictionary<string,ParameterMetadata>();
  129. MethodBase m = GetCallingMethod(DS.List("GetLocalsEx"));
  130. int i = 0;
  131. foreach(var mp in m.GetParameters())
  132. dic.Add(mp.Name, new ParameterMetadata(mp, parameterValues[i++]));
  133. return dic;
  134. }
  135. /// <summary>
  136. /// Clone a dictionary
  137. /// </summary>
  138. /// <typeparam name="K"></typeparam>
  139. /// <typeparam name="V"></typeparam>
  140. /// <param name="dic"></param>
  141. /// <returns></returns>
  142. public static Dictionary<K,V> CloneDictionary<K,V>(IDictionary<K,V> dic){
  143. Dictionary<K,V> d = new Dictionary<K,V>();
  144. foreach(KeyValuePair<K,V> v in dic)
  145. d.Add(v.Key, v.Value);
  146. return d;
  147. }
  148. /// <summary>
  149. ///
  150. /// </summary>
  151. /// <typeparam name="K"></typeparam>
  152. /// <typeparam name="V"></typeparam>
  153. /// <param name="dic1"></param>
  154. /// <param name="dic2"></param>
  155. /// <param name="overwrite"></param>
  156. /// <returns></returns>
  157. public static Dictionary<K,V> MergeDictionary<K,V>(IDictionary<K,V> dic1, IDictionary<K,V> dic2, bool overwrite = false){
  158. Dictionary<K,V> d = CloneDictionary(dic1);
  159. foreach(KeyValuePair<K,V> v in dic2)
  160. if(overwrite){
  161. if(d.ContainsKey(v.Key))
  162. d.Remove(v.Key);
  163. d.Add(v.Key, v.Value);
  164. }
  165. else{
  166. if(!d.ContainsKey(v.Key))
  167. d.Add(v.Key, v.Value);
  168. }
  169. return d;
  170. }
  171. #if USE_FAST_REFLECTION
  172. private static Dictionary<string, List<string>> __TypeDefined = new Dictionary<string, List<string>>();
  173. #endif
  174. /// <summary>
  175. ///
  176. /// </summary>
  177. /// <param name="o"></param>
  178. /// <returns></returns>
  179. public static Dictionary<string,object> GetDictionary(object o, List<string> propertiesToInclude = null) {
  180. var dic = new Dictionary<string,object>();
  181. // Support Dictionary and ExpandoObect
  182. if(o is IDictionary<string, object>) {
  183. // We have to make a copy, because returning an ExpandoObject as an IDictionary, do not support the dic["name"] syntax.
  184. foreach(KeyValuePair<string, object> v in ((IDictionary<string, object>)o))
  185. if((propertiesToInclude==null)||(propertiesToInclude.Contains(v.Key)))
  186. dic.Add(v.Key, v.Value);
  187. return dic;
  188. }
  189. #if USE_FAST_REFLECTION
  190. var typeFullName = o.GetType().FullName;
  191. if (!__TypeDefined.ContainsKey(typeFullName))
  192. {
  193. var l = new List<string>();
  194. foreach (var k in DynamicSugar.ReflectionHelper.GetDictionaryReflection(o))
  195. l.Add(k.Key);
  196. __TypeDefined.Add(typeFullName, l);
  197. }
  198. foreach (var p in __TypeDefined[typeFullName]) {
  199. var pp = o.GetType().GetProperty(p);
  200. if(pp==null)
  201. throw new System.ApplicationException("Field '{0}' in object '{1}' is not supported. Only properties are supported".FormatString(p, o));
  202. dic.Add(p, FastProperty<object, object>.Make(pp).Get(o));
  203. }
  204. #else
  205. dic = DynamicSugar.ReflectionHelper.GetDictionaryReflection(o, propertiesToInclude);
  206. #endif
  207. return dic;
  208. }
  209. /// <summary>
  210. /// Get a dictionary from an poco object using reflection only
  211. /// </summary>
  212. /// <param name="o"></param>
  213. /// <param name="propertiesToInclude"></param>
  214. /// <returns></returns>
  215. private static Dictionary<string,object> GetDictionaryReflection(object o, List<string> propertiesToInclude = null) {
  216. var dic = new Dictionary<string,object>();
  217. foreach(var p in o.GetType().GetProperties(GET_FLAGS))
  218. if((propertiesToInclude==null)||(propertiesToInclude.Contains(p.Name)))
  219. dic.Add( p.Name, p.GetValue(o, new object[0]) );
  220. foreach(var p in o.GetType().GetFields(GET_FLAGS))
  221. if((propertiesToInclude==null)||(propertiesToInclude.Contains(p.Name)))
  222. dic.Add( p.Name, p.GetValue(o) );
  223. return dic;
  224. }
  225. /// <summary>
  226. ///
  227. /// </summary>
  228. /// <param name="o"></param>
  229. /// <param name="propertyName"></param>
  230. /// <returns></returns>
  231. public static bool PropertyExist(object o, string propertyName) {
  232. try {
  233. object oValue = o.GetType().InvokeMember(propertyName, GET_FLAGS, null, o, null);
  234. return true;
  235. }
  236. catch {
  237. return false;
  238. }
  239. }
  240. public static bool MethodExist(object o, string methodName)
  241. {
  242. try
  243. {
  244. return o.GetType().GetMethod(methodName) != null;
  245. }
  246. catch (AmbiguousMatchException)
  247. {
  248. return true; // ambiguous means there is more than one result which means: a method with that name does exist
  249. }
  250. }
  251. /// <summary>
  252. ///
  253. /// </summary>
  254. /// <param name="o"></param>
  255. /// <param name="propertyName"></param>
  256. /// <returns></returns>
  257. public static object GetProperty(object o, string propertyName, object defaultValue = null) {
  258. try {
  259. object oValue = o.GetType().InvokeMember(propertyName, GET_FLAGS, null, o, null);
  260. return oValue;
  261. }
  262. catch {
  263. return defaultValue;
  264. }
  265. }
  266. /// <summary>
  267. ///
  268. /// </summary>
  269. /// <param name="o"></param>
  270. /// <param name="propertyName"></param>
  271. /// <param name="defaultValue"></param>
  272. /// <returns></returns>
  273. public static object GetPropertyStatic(Type o, string propertyName, object defaultValue = null)
  274. {
  275. try
  276. {
  277. object oValue = o.InvokeMember(propertyName, GET_FLAGS_STATIC, null, null, null);
  278. return oValue;
  279. }
  280. catch(System.Exception ex)
  281. {
  282. throw;
  283. }
  284. }
  285. public enum IndexerType {
  286. Get,
  287. Set
  288. }
  289. /// <summary>
  290. /// Return the name of the indexer function for a get or a set
  291. /// </summary>
  292. /// <param name="o">The instance</param>
  293. /// <param name="indexerType">Define get or set</param>
  294. /// <returns></returns>
  295. private static string GetIndexerMethodName(object o, IndexerType indexerType) {
  296. foreach (PropertyInfo property in o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
  297. if (property.GetIndexParameters().Length > 0)
  298. {
  299. return string.Format("{0}_{1}", indexerType.ToString().ToLowerInvariant(), property.Name);
  300. }
  301. }
  302. return null;
  303. }
  304. /// <summary>
  305. ///
  306. /// </summary>
  307. /// <param name="instance"></param>
  308. /// <param name="method"></param>
  309. /// <param name="parameters"></param>
  310. /// <returns></returns>
  311. public static object GetIndexer(object instance, params object[] parameters)
  312. {
  313. try
  314. {
  315. if(instance == null)
  316. throw new ArgumentException("Instance null has not indexer");
  317. var getIndexerMethod = GetIndexerMethodName(instance, IndexerType.Get);
  318. if(getIndexerMethod == null)
  319. throw new ArgumentException(string.Format("Type:{0} has not indexer", instance.GetType().FullName));
  320. var v = ReflectionHelper.ExecuteMethod(instance, getIndexerMethod, parameters);
  321. return v;
  322. }
  323. catch(System.Exception ex)
  324. {
  325. throw;
  326. }
  327. }
  328. /// <summary>
  329. ///
  330. /// </summary>
  331. /// <param name="instance"></param>
  332. /// <param name="parameters"></param>
  333. /// <returns></returns>
  334. public static object SetIndexer(object instance, params object[] parameters)
  335. {
  336. try
  337. {
  338. if(instance == null)
  339. throw new ArgumentException("Instance null has not indexer");
  340. var getIndexerMethod = GetIndexerMethodName(instance, IndexerType.Set);
  341. if(getIndexerMethod == null)
  342. throw new ArgumentException(string.Format("Type:{0} has not indexer", instance.GetType().FullName));
  343. var v = ReflectionHelper.ExecuteMethod(instance, getIndexerMethod, parameters);
  344. return v;
  345. }
  346. catch(System.Exception ex)
  347. {
  348. throw;
  349. }
  350. }
  351. /// <summary>
  352. ///
  353. /// </summary>
  354. /// <param name="o"></param>
  355. /// <param name="strPropertyName"></param>
  356. /// <param name="Value"></param>
  357. /// <param name="setIfNull"></param>
  358. public static void SetProperty(object o, string strPropertyName, object Value, bool setIfNull = false){
  359. if (o == null)throw new System.ArgumentException("parameter o cannot be null");
  360. if ((!setIfNull) && (Value == null)) return;
  361. object[] PropertyValue = new object[1];
  362. PropertyValue[0] = Value;
  363. o.GetType().InvokeMember(strPropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetField | BindingFlags.SetProperty | BindingFlags.IgnoreCase, null, o, PropertyValue);
  364. }
  365. /// <summary>
  366. ///
  367. /// </summary>
  368. /// <param name="instance"></param>
  369. /// <param name="method"></param>
  370. /// <param name="parameters"></param>
  371. /// <returns></returns>
  372. public static object ExecuteMethod(object instance, string method, params object[] parameters) {
  373. object retValue;
  374. if (parameters.Length == 0)
  375. retValue = instance.GetType().InvokeMember(method, CALL_METHOD_FLAGS, null, instance, null);
  376. else
  377. retValue = instance.GetType().InvokeMember(method, CALL_METHOD_FLAGS, null, instance, parameters);
  378. return retValue;
  379. }
  380. /// <summary>
  381. /// Execute a static method
  382. /// </summary>
  383. /// <param name="type"></param>
  384. /// <param name="method"></param>
  385. /// <param name="parameters"></param>
  386. /// <returns></returns>
  387. public static object ExecuteStaticMethod(Type type, string method, params object[] parameters) {
  388. object retValue;
  389. if (parameters.Length == 0)
  390. retValue = type.InvokeMember(method, CALL_STATIC_METHOD_FLAGS, null, null, null);
  391. else
  392. retValue = type.InvokeMember(method, CALL_STATIC_METHOD_FLAGS, null, null, parameters);
  393. return retValue;
  394. }
  395. /// <summary>
  396. /// Returns the type of a generic List
  397. /// </summary>
  398. /// <param name="type"></param>
  399. /// <returns></returns>
  400. public static Type GetListType(Type type) {
  401. foreach (Type intType in type.GetInterfaces())
  402. if (intType.IsGenericType && intType.GetGenericTypeDefinition() == typeof(IList<>))
  403. return intType.GetGenericArguments()[0];
  404. return null;
  405. }
  406. /// <summary>
  407. /// Returns the type of the key and of the value for a
  408. /// generic Dictionary
  409. /// </summary>
  410. /// <param name="type"></param>
  411. /// <param name="keyType"></param>
  412. /// <param name="valueType"></param>
  413. /// <returns></returns>
  414. public static bool GetDictionaryType(Type type, out Type keyType, out Type valueType) {
  415. keyType = null;
  416. valueType = null;
  417. if (type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
  418. Type[] typeParameters = type.GetGenericArguments();
  419. keyType = typeParameters[0];
  420. valueType = typeParameters[1];
  421. return true;
  422. }
  423. else return false;
  424. }
  425. /// <summary>
  426. ///
  427. /// </summary>
  428. /// <param name="t"></param>
  429. /// <returns></returns>
  430. public static bool IsDictionaryOfKV(Type t){
  431. if(t.IsGenericType)
  432. return (t.GetGenericTypeDefinition() == typeof(Dictionary<,>));
  433. return false;
  434. }
  435. /// <summary>
  436. ///
  437. /// </summary>
  438. /// <param name="t"></param>
  439. /// <returns></returns>
  440. public static bool IsTypeListOfT(Type t){
  441. if(t.IsGenericType)
  442. return (t.GetGenericTypeDefinition() == typeof(List<>));
  443. return false;
  444. }
  445. }
  446. }