PageRenderTime 39ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/MVC.Controls/AttributeHelper.cs

#
C# | 271 lines | 217 code | 49 blank | 5 comment | 31 complexity | 7ce56651222b47fda80a66e4d7bc5bd4 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Linq.Expressions;
  6. using System.Reflection;
  7. using System.ComponentModel.DataAnnotations;
  8. namespace MVC.Controls
  9. {
  10. public static class AttributeHelper
  11. {
  12. private static Dictionary<object, List<Attribute>> _attributeCache = new Dictionary<object, List<Attribute>>();
  13. public static Dictionary<object, List<Attribute>> AttributeCache { get { return _attributeCache; } }
  14. // Types
  15. public static List<Attribute> GetTypeAttributes<TType>()
  16. {
  17. return GetTypeAttributes(typeof(TType));
  18. }
  19. public static List<Attribute> GetTypeAttributes(Type type)
  20. {
  21. return LockAndGetAttributes(type, tp => ((Type)tp).GetCustomAttributes(true));
  22. }
  23. public static List<TAttributeType> GetTypeAttributes<TAttributeType>(Type type, Func<TAttributeType, bool> predicate = null)
  24. {
  25. return
  26. GetTypeAttributes(type)
  27. .OfType<TAttributeType>()
  28. .Where(attr => predicate == null || predicate(attr))
  29. .ToList();
  30. }
  31. public static List<TAttributeType> GetTypeAttributes<TType, TAttributeType>(Func<TAttributeType, bool> predicate = null)
  32. {
  33. return GetTypeAttributes(typeof(TType), predicate);
  34. }
  35. public static TAttributeType GetTypeAttribute<TType, TAttributeType>(Func<TAttributeType, bool> predicate = null)
  36. {
  37. return
  38. GetTypeAttribute(typeof(TType), predicate);
  39. }
  40. public static TAttributeType GetTypeAttribute<TAttributeType>(Type type, Func<TAttributeType, bool> predicate = null)
  41. {
  42. return
  43. GetTypeAttributes<TAttributeType>(type, predicate)
  44. .FirstOrDefault();
  45. }
  46. public static bool HasTypeAttribute<TType, TAttributeType>(Func<TAttributeType, bool> predicate = null)
  47. {
  48. return HasTypeAttribute<TAttributeType>(typeof(TType), predicate);
  49. }
  50. public static bool HasTypeAttribute<TAttributeType>(Type type, Func<TAttributeType, bool> predicate = null)
  51. {
  52. return GetTypeAttribute<TAttributeType>(type, predicate) != null;
  53. }
  54. // Members and properties
  55. public static List<Attribute> GetMemberAttributes<TType>(Expression<Func<TType, object>> action)
  56. {
  57. return GetMemberAttributes(GetMember(action));
  58. }
  59. public static List<TAttributeType> GetMemberAttributes<TType, TAttributeType>(
  60. Expression<Func<TType, object>> action,
  61. Func<TAttributeType, bool> predicate = null)
  62. where TAttributeType : Attribute
  63. {
  64. return GetMemberAttributes<TAttributeType>(GetMember(action), predicate);
  65. }
  66. public static TAttributeType GetMemberAttribute<TType, TAttributeType>(
  67. Expression<Func<TType, object>> action,
  68. Func<TAttributeType, bool> predicate = null)
  69. where TAttributeType : Attribute
  70. {
  71. return GetMemberAttribute<TAttributeType>(GetMember(action), predicate);
  72. }
  73. public static bool HasMemberAttribute<TType, TAttributeType>(Expression<Func<TType, object>> action, Func<TAttributeType, bool> predicate = null) where TAttributeType : Attribute
  74. {
  75. return GetMemberAttribute(GetMember(action), predicate) != null;
  76. }
  77. // MemberInfo (and PropertyInfo since PropertyInfo inherits from MemberInfo)
  78. public static List<Attribute> GetMemberAttributes(this MemberInfo memberInfo)
  79. {
  80. return
  81. LockAndGetAttributes(memberInfo, mi => GetMemberAttributesWithMeta((MemberInfo)mi).ToArray());
  82. }
  83. public static List<Attribute> GetMemberAttributesWithMeta(this MemberInfo mi)
  84. {
  85. List<Attribute> result =
  86. mi
  87. .GetCustomAttributes(true)
  88. .OfType<Attribute>()
  89. .ToList();
  90. foreach(MetadataTypeAttribute meta in GetTypeAttributes<MetadataTypeAttribute>(mi.DeclaringType))
  91. {
  92. MemberInfo[] metaMembers = meta.MetadataClassType.GetMember(mi.Name);
  93. foreach(MemberInfo mi2 in metaMembers)
  94. {
  95. result.AddRange(mi2.GetCustomAttributes(true).OfType<Attribute>());
  96. }
  97. }
  98. return result;
  99. }
  100. public static List<TAttributeType> GetMemberAttributes<TAttributeType>(this MemberInfo memberInfo, Func<TAttributeType, bool> predicate = null) where TAttributeType : Attribute
  101. {
  102. return
  103. GetMemberAttributes(memberInfo)
  104. .OfType<TAttributeType>()
  105. .Where(attr => predicate == null || predicate(attr))
  106. .ToList();
  107. }
  108. public static TAttributeType GetMemberAttribute<TAttributeType>(this MemberInfo memberInfo, Func<TAttributeType, bool> predicate = null) where TAttributeType : Attribute
  109. {
  110. return
  111. GetMemberAttributes<TAttributeType>(memberInfo, predicate)
  112. .FirstOrDefault();
  113. }
  114. public static bool HasMemberAttribute<TAttributeType>(this MemberInfo memberInfo, Func<TAttributeType, bool> predicate = null) where TAttributeType : Attribute
  115. {
  116. return
  117. memberInfo.GetMemberAttribute<TAttributeType>(predicate) != null;
  118. }
  119. // Internal stuff
  120. private static TType FirstOrDefault<TX, TType>(this IEnumerable<TX> list)
  121. {
  122. return
  123. list
  124. .OfType<TType>()
  125. .FirstOrDefault();
  126. }
  127. private static List<Attribute> LockAndGetAttributes(object key, Func<object, object[]> retrieveValue)
  128. {
  129. return
  130. LockAndGet<object, List<Attribute>>(_attributeCache, key, mi => retrieveValue(mi).Cast<Attribute>().ToList());
  131. }
  132. // Method for thread safely executing slow method and storing the result in a dictionary
  133. private static TValue LockAndGet<TKey, TValue>(Dictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> retrieveValue)
  134. {
  135. TValue value = default(TValue);
  136. lock (dictionary)
  137. {
  138. if (dictionary.TryGetValue(key, out value))
  139. {
  140. return value;
  141. }
  142. }
  143. value = retrieveValue(key);
  144. lock (dictionary)
  145. {
  146. if (dictionary.ContainsKey(key) == false)
  147. {
  148. dictionary.Add(key, value);
  149. }
  150. return value;
  151. }
  152. }
  153. public static MemberInfo GetMember<T>(Expression<Func<T, object>> expression)
  154. {
  155. MemberExpression memberExpression = expression.Body as MemberExpression;
  156. if (memberExpression != null)
  157. {
  158. return memberExpression.Member;
  159. }
  160. UnaryExpression unaryExpression = expression.Body as UnaryExpression;
  161. if (unaryExpression != null)
  162. {
  163. memberExpression = unaryExpression.Operand as MemberExpression;
  164. if (memberExpression != null)
  165. {
  166. return memberExpression.Member;
  167. }
  168. MethodCallExpression methodCall = unaryExpression.Operand as MethodCallExpression;
  169. if (methodCall != null)
  170. {
  171. return methodCall.Method;
  172. }
  173. }
  174. return null;
  175. }
  176. public static bool IsMember<T>(Expression<Func<T, object>> expression)
  177. {
  178. return GetMember<T>(expression) != null;
  179. }
  180. public static string GetMemberName<T>(T example, Expression<Func<T, object>> expression) where T : class
  181. {
  182. MemberExpression memberExpression = GetMemberExpression(expression);
  183. if (memberExpression == null)
  184. {
  185. return null;
  186. }
  187. if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
  188. {
  189. MemberExpression innerMemberExpression = (MemberExpression)memberExpression.Expression;
  190. return memberExpression.ToString().Substring(innerMemberExpression.Expression.ToString().Length + 1);
  191. }
  192. return memberExpression.Member.Name;
  193. }
  194. public static string GetMemberName<T>(Expression<Func<T, object>> expression) where T : class
  195. {
  196. MemberExpression memberExpression = GetMemberExpression(expression);
  197. if (memberExpression == null)
  198. {
  199. return null;
  200. }
  201. if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
  202. {
  203. MemberExpression innerMemberExpression = (MemberExpression)memberExpression.Expression;
  204. return memberExpression.ToString().Substring(innerMemberExpression.Expression.ToString().Length + 1);
  205. }
  206. return memberExpression.Member.Name;
  207. }
  208. public static MemberExpression GetMemberExpression<T>(Expression<Func<T, object>> expression) where T : class
  209. {
  210. MemberExpression memberExpression = expression.Body as MemberExpression;
  211. if (memberExpression == null)
  212. {
  213. UnaryExpression unaryExpression = expression.Body as UnaryExpression;
  214. if (unaryExpression != null)
  215. {
  216. memberExpression = unaryExpression.Operand as MemberExpression;
  217. }
  218. }
  219. return memberExpression;
  220. }
  221. }
  222. }