PageRenderTime 52ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/corlib/System/Attribute.cs

https://github.com/iainlane/mono
C# | 444 lines | 292 code | 87 blank | 65 comment | 44 complexity | aeb9df3abb8cd54d222d4e04720c0348 MD5 | raw file
  1. //
  2. // System.Attribute.cs
  3. //
  4. // Authors:
  5. // Miguel de Icaza (miguel@ximian.com) - Original
  6. // Nick D. Drochak II (ndrochak@gol.com) - Implemented most of the guts
  7. // Gonzalo Paniagua Javier (gonzalo@ximian.com)
  8. //
  9. // (C) 2002, 2003 Ximian, Inc. http://www.ximian.com
  10. // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System.Collections.Generic;
  32. using System.Reflection;
  33. using System.Runtime.InteropServices;
  34. namespace System
  35. {
  36. [AttributeUsage (AttributeTargets.All)]
  37. [Serializable]
  38. [ComVisible (true)]
  39. [ComDefaultInterface (typeof (_Attribute))]
  40. [ClassInterfaceAttribute (ClassInterfaceType.None)]
  41. public abstract class Attribute : _Attribute {
  42. protected Attribute ()
  43. {
  44. }
  45. public virtual object TypeId {
  46. get {
  47. // Derived classes should override this default behaviour as appropriate
  48. return this.GetType ();
  49. }
  50. }
  51. private static void CheckParameters (object element, Type attributeType)
  52. {
  53. // neither parameter is allowed to be null
  54. if (element == null)
  55. throw new ArgumentNullException ("element");
  56. if (attributeType == null)
  57. throw new ArgumentNullException ("attributeType");
  58. if (!typeof (Attribute).IsAssignableFrom (attributeType))
  59. throw new ArgumentException (Locale.GetText (
  60. "Type is not derived from System.Attribute."), "attributeType");
  61. }
  62. private static Attribute FindAttribute (object[] attributes)
  63. {
  64. // if there exists more than one attribute of the given type, throw an exception
  65. if (attributes.Length > 1) {
  66. throw new AmbiguousMatchException (Locale.GetText (
  67. "<element> has more than one attribute of type <attribute_type>"));
  68. }
  69. if (attributes.Length < 1)
  70. return null;
  71. // tested above for '> 1' and and '< 1', so only '== 1' is left,
  72. // i.e. we found the attribute
  73. return (Attribute) attributes[0];
  74. }
  75. public static Attribute GetCustomAttribute (ParameterInfo element, Type attributeType)
  76. {
  77. return GetCustomAttribute (element, attributeType, true);
  78. }
  79. public static Attribute GetCustomAttribute (MemberInfo element, Type attributeType)
  80. {
  81. return GetCustomAttribute (element, attributeType, true);
  82. }
  83. public static Attribute GetCustomAttribute (Assembly element, Type attributeType)
  84. {
  85. return GetCustomAttribute (element, attributeType, true);
  86. }
  87. public static Attribute GetCustomAttribute (Module element, Type attributeType)
  88. {
  89. return GetCustomAttribute (element, attributeType, true);
  90. }
  91. public static Attribute GetCustomAttribute (Module element, Type attributeType, bool inherit)
  92. {
  93. // neither parameter is allowed to be null
  94. CheckParameters (element, attributeType);
  95. // Module inheritance hierarchies CAN NOT be searched for attributes, so the second
  96. // parameter of GetCustomAttributes () is IGNORED.
  97. object[] attributes = element.GetCustomAttributes (attributeType, inherit);
  98. return FindAttribute (attributes);
  99. }
  100. public static Attribute GetCustomAttribute (Assembly element, Type attributeType, bool inherit)
  101. {
  102. // neither parameter is allowed to be null
  103. CheckParameters (element, attributeType);
  104. // Assembly inheritance hierarchies CAN NOT be searched for attributes, so the second
  105. // parameter of GetCustomAttributes () is IGNORED.
  106. object[] attributes = element.GetCustomAttributes (attributeType, inherit);
  107. return FindAttribute (attributes);
  108. }
  109. public static Attribute GetCustomAttribute (ParameterInfo element, Type attributeType, bool inherit)
  110. {
  111. // neither parameter is allowed to be null
  112. CheckParameters (element, attributeType);
  113. object[] attributes = GetCustomAttributes (element, attributeType, inherit);
  114. return FindAttribute (attributes);
  115. }
  116. public static Attribute GetCustomAttribute (MemberInfo element, Type attributeType, bool inherit)
  117. {
  118. // neither parameter is allowed to be null
  119. CheckParameters (element, attributeType);
  120. // MemberInfo inheritance hierarchies can be searched for attributes, so the second
  121. // parameter of GetCustomAttribute () is respected.
  122. return MonoCustomAttrs.GetCustomAttribute (element, attributeType, inherit);
  123. }
  124. public static Attribute[] GetCustomAttributes (Assembly element)
  125. {
  126. return GetCustomAttributes (element, true);
  127. }
  128. public static Attribute[] GetCustomAttributes (ParameterInfo element)
  129. {
  130. return GetCustomAttributes (element, true);
  131. }
  132. public static Attribute[] GetCustomAttributes (MemberInfo element)
  133. {
  134. return GetCustomAttributes (element, true);
  135. }
  136. public static Attribute[] GetCustomAttributes (Module element)
  137. {
  138. return GetCustomAttributes (element, true);
  139. }
  140. public static Attribute[] GetCustomAttributes (Assembly element, Type attributeType)
  141. {
  142. return GetCustomAttributes (element, attributeType, true);
  143. }
  144. public static Attribute[] GetCustomAttributes (Module element, Type attributeType)
  145. {
  146. return GetCustomAttributes (element, attributeType, true);
  147. }
  148. public static Attribute[] GetCustomAttributes (ParameterInfo element, Type attributeType)
  149. {
  150. return GetCustomAttributes (element, attributeType, true);
  151. }
  152. public static Attribute[] GetCustomAttributes (MemberInfo element, Type type)
  153. {
  154. return GetCustomAttributes (element, type, true);
  155. }
  156. public static Attribute[] GetCustomAttributes (Assembly element, Type attributeType, bool inherit)
  157. {
  158. // element parameter is not allowed to be null
  159. CheckParameters (element, attributeType);
  160. return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
  161. }
  162. public static Attribute[] GetCustomAttributes (ParameterInfo element, Type attributeType, bool inherit)
  163. {
  164. // element parameter is not allowed to be null
  165. CheckParameters (element, attributeType);
  166. Attribute [] attributes;
  167. if (inherit && TryGetParamCustomAttributes (element, attributeType, out attributes))
  168. return attributes;
  169. return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
  170. }
  171. public static Attribute[] GetCustomAttributes (Module element, Type attributeType, bool inherit)
  172. {
  173. // element parameter is not allowed to be null
  174. CheckParameters (element, attributeType);
  175. return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
  176. }
  177. public static Attribute[] GetCustomAttributes (MemberInfo element, Type type, bool inherit)
  178. {
  179. // element parameter is not allowed to be null
  180. CheckParameters (element, type);
  181. // MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider
  182. // implementation, but not in the Attributes, so directly get the attributes
  183. // from MonoCustomAttrs instead of going throught the PropertyInfo's
  184. // ICustomAttributeProvider
  185. MemberTypes mtype = element.MemberType;
  186. if (mtype == MemberTypes.Property)
  187. return (Attribute []) MonoCustomAttrs.GetCustomAttributes (element, type, inherit);
  188. return (Attribute []) element.GetCustomAttributes (type, inherit);
  189. }
  190. public static Attribute[] GetCustomAttributes (Module element, bool inherit)
  191. {
  192. return GetCustomAttributes (element, typeof (Attribute), inherit);
  193. }
  194. public static Attribute[] GetCustomAttributes (Assembly element, bool inherit)
  195. {
  196. return GetCustomAttributes (element, typeof (Attribute), inherit);
  197. }
  198. public static Attribute[] GetCustomAttributes (MemberInfo element, bool inherit)
  199. {
  200. return GetCustomAttributes (element, typeof (Attribute), inherit);
  201. }
  202. public static Attribute[] GetCustomAttributes (ParameterInfo element, bool inherit)
  203. {
  204. // element parameter is not allowed to be null
  205. CheckParameters (element, typeof (Attribute));
  206. return GetCustomAttributes (element, typeof (Attribute), inherit);
  207. }
  208. public override int GetHashCode ()
  209. {
  210. int result = TypeId.GetHashCode ();
  211. FieldInfo[] fields = GetType ().GetFields (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  212. foreach (FieldInfo field in fields) {
  213. object value = field.GetValue (this);
  214. result ^= value == null ? 0 : value.GetHashCode ();
  215. }
  216. return result;
  217. }
  218. public virtual bool IsDefaultAttribute ()
  219. {
  220. // Derived classes should override this default behaviour as appropriate
  221. return false;
  222. }
  223. public static bool IsDefined (Module element, Type attributeType)
  224. {
  225. return IsDefined (element, attributeType, false);
  226. }
  227. public static bool IsDefined (ParameterInfo element, Type attributeType)
  228. {
  229. return IsDefined (element, attributeType, true);
  230. }
  231. public static bool IsDefined (MemberInfo element, Type attributeType)
  232. {
  233. return IsDefined (element, attributeType, true);
  234. }
  235. public static bool IsDefined (Assembly element, Type attributeType)
  236. {
  237. return IsDefined (element, attributeType, true);
  238. }
  239. public static bool IsDefined (MemberInfo element, Type attributeType, bool inherit)
  240. {
  241. CheckParameters (element, attributeType);
  242. MemberTypes mtype = element.MemberType;
  243. if (mtype != MemberTypes.Constructor && mtype != MemberTypes.Event &&
  244. mtype != MemberTypes.Field && mtype != MemberTypes.Method &&
  245. mtype != MemberTypes.Property && mtype != MemberTypes.TypeInfo &&
  246. mtype != MemberTypes.NestedType)
  247. throw new NotSupportedException (Locale.GetText (
  248. "Element is not a constructor, method, property, event, type or field."));
  249. // MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider
  250. // implementation, but not in the Attributes, so directly get the attributes
  251. // from MonoCustomAttrs instead of going throught the PropertyInfo's
  252. // ICustomAttributeProvider
  253. if (mtype == MemberTypes.Property)
  254. return MonoCustomAttrs.IsDefined (element, attributeType, inherit);
  255. return ((MemberInfo) element).IsDefined (attributeType, inherit);
  256. }
  257. public static bool IsDefined (Assembly element, Type attributeType, bool inherit)
  258. {
  259. CheckParameters (element, attributeType);
  260. return element.IsDefined (attributeType, inherit);
  261. }
  262. public static bool IsDefined (Module element, Type attributeType, bool inherit)
  263. {
  264. CheckParameters (element, attributeType);
  265. return element.IsDefined (attributeType, inherit);
  266. }
  267. public static bool IsDefined (ParameterInfo element, Type attributeType, bool inherit)
  268. {
  269. CheckParameters (element, attributeType);
  270. if (element.IsDefined (attributeType, inherit))
  271. return true;
  272. if (inherit)
  273. return IsDefinedOnParameter (element, attributeType);
  274. return false;
  275. }
  276. static bool IsDefinedOnParameter (ParameterInfo parameter, Type attributeType)
  277. {
  278. var member = parameter.Member;
  279. if (member.MemberType != MemberTypes.Method)
  280. return false;
  281. var method = ((MethodInfo) member).GetBaseMethod ();
  282. while (true) {
  283. var param = method.GetParameters () [parameter.Position];
  284. if (param.IsDefined (attributeType, false))
  285. return true;
  286. var base_method = method.GetBaseMethod ();
  287. if (base_method == method)
  288. break;
  289. method = base_method;
  290. }
  291. return false;
  292. }
  293. static bool TryGetParamCustomAttributes (ParameterInfo parameter, Type attributeType, out Attribute [] attributes)
  294. {
  295. attributes = null;
  296. if (parameter.Member.MemberType != MemberTypes.Method)
  297. return false;
  298. var method = (MethodInfo) parameter.Member;
  299. var definition = method.GetBaseDefinition ();
  300. if (method == definition)
  301. return false;
  302. var types = new List<Type> ();
  303. var custom_attributes = new List<Attribute> ();
  304. while (true) {
  305. var param = method.GetParameters () [parameter.Position];
  306. var param_attributes = (Attribute []) param.GetCustomAttributes (attributeType, false);
  307. foreach (var param_attribute in param_attributes) {
  308. var param_type = param_attribute.GetType ();
  309. if (types.Contains (param_type))
  310. continue;
  311. types.Add (param_type);
  312. custom_attributes.Add (param_attribute);
  313. }
  314. var base_method = method.GetBaseMethod ();
  315. if (base_method == method)
  316. break;
  317. method = base_method;
  318. }
  319. attributes = (Attribute []) Array.CreateInstance (attributeType, custom_attributes.Count);
  320. custom_attributes.CopyTo (attributes, 0);
  321. return true;
  322. }
  323. public virtual bool Match (object obj)
  324. {
  325. // default action is the same as Equals.
  326. // Derived classes should override as appropriate
  327. return this.Equals (obj);
  328. }
  329. public override bool Equals (object obj)
  330. {
  331. if (obj == null || !(obj is Attribute))
  332. return false;
  333. //
  334. // This is needed because Attribute.Equals does a deep
  335. // compare. Ran into this with vbnc
  336. //
  337. return ValueType.DefaultEquals (this, obj);
  338. }
  339. void _Attribute.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
  340. {
  341. throw new NotImplementedException ();
  342. }
  343. void _Attribute.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
  344. {
  345. throw new NotImplementedException ();
  346. }
  347. void _Attribute.GetTypeInfoCount (out uint pcTInfo)
  348. {
  349. throw new NotImplementedException ();
  350. }
  351. void _Attribute.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
  352. IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
  353. {
  354. throw new NotImplementedException ();
  355. }
  356. }
  357. }