RuntimeParameterInfo.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. // System.Reflection.RuntimeParameterInfo
  2. //
  3. // Authors:
  4. // Sean MacIsaac ([email protected])
  5. // Marek Safar ([email protected])
  6. //
  7. // (C) 2001 Ximian, Inc.
  8. // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
  9. // Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. #if MONO_FEATURE_SRE
  31. using System.Reflection.Emit;
  32. #endif
  33. using System.Runtime.CompilerServices;
  34. using System.Runtime.InteropServices;
  35. using System.Collections.Generic;
  36. using System.Text;
  37. namespace System.Reflection
  38. {
  39. #if !NETCORE
  40. [ComVisible (true)]
  41. [ComDefaultInterfaceAttribute (typeof (_ParameterInfo))]
  42. [Serializable]
  43. [ClassInterfaceAttribute (ClassInterfaceType.None)]
  44. #endif
  45. [StructLayout (LayoutKind.Sequential)]
  46. class RuntimeParameterInfo : ParameterInfo {
  47. internal MarshalAsAttribute marshalAs;
  48. internal static void FormatParameters (StringBuilder sb, ParameterInfo[] p, CallingConventions callingConvention, bool serialization)
  49. {
  50. #if NETCORE
  51. throw new NotImplementedException ();
  52. #else
  53. for (int i = 0; i < p.Length; ++i) {
  54. if (i > 0)
  55. sb.Append (", ");
  56. Type t = p[i].ParameterType;
  57. string typeName = t.FormatTypeName (serialization);
  58. // Legacy: Why use "ByRef" for by ref parameters? What language is this?
  59. // VB uses "ByRef" but it should precede (not follow) the parameter name.
  60. // Why don't we just use "&"?
  61. if (t.IsByRef && !serialization) {
  62. sb.Append (typeName.TrimEnd (new char[] { '&' }));
  63. sb.Append (" ByRef");
  64. } else {
  65. sb.Append (typeName);
  66. }
  67. }
  68. if ((callingConvention & CallingConventions.VarArgs) != 0) {
  69. if (p.Length > 0)
  70. sb.Append (", ");
  71. sb.Append ("...");
  72. }
  73. #endif
  74. }
  75. #if MONO_FEATURE_SRE
  76. internal RuntimeParameterInfo (ParameterBuilder pb, Type type, MemberInfo member, int position) {
  77. this.ClassImpl = type;
  78. this.MemberImpl = member;
  79. if (pb != null) {
  80. this.NameImpl = pb.Name;
  81. this.PositionImpl = pb.Position - 1; // ParameterInfo.Position is zero-based
  82. this.AttrsImpl = (ParameterAttributes) pb.Attributes;
  83. } else {
  84. this.NameImpl = null;
  85. this.PositionImpl = position - 1;
  86. this.AttrsImpl = ParameterAttributes.None;
  87. }
  88. }
  89. internal static ParameterInfo New (ParameterBuilder pb, Type type, MemberInfo member, int position)
  90. {
  91. return new RuntimeParameterInfo (pb, type, member, position);
  92. }
  93. #endif
  94. /*FIXME this constructor looks very broken in the position parameter*/
  95. internal RuntimeParameterInfo (ParameterInfo pinfo, Type type, MemberInfo member, int position) {
  96. this.ClassImpl = type;
  97. this.MemberImpl = member;
  98. if (pinfo != null) {
  99. this.NameImpl = pinfo.Name;
  100. this.PositionImpl = pinfo.Position - 1; // ParameterInfo.Position is zero-based
  101. this.AttrsImpl = (ParameterAttributes) pinfo.Attributes;
  102. } else {
  103. this.NameImpl = null;
  104. this.PositionImpl = position - 1;
  105. this.AttrsImpl = ParameterAttributes.None;
  106. }
  107. }
  108. internal RuntimeParameterInfo (ParameterInfo pinfo, MemberInfo member) {
  109. this.ClassImpl = pinfo.ParameterType;
  110. this.MemberImpl = member;
  111. this.NameImpl = pinfo.Name;
  112. this.PositionImpl = pinfo.Position;
  113. this.AttrsImpl = pinfo.Attributes;
  114. this.DefaultValueImpl = GetDefaultValueImpl (pinfo);
  115. }
  116. /* to build a ParameterInfo for the return type of a method */
  117. internal RuntimeParameterInfo (Type type, MemberInfo member, MarshalAsAttribute marshalAs) {
  118. this.ClassImpl = type;
  119. this.MemberImpl = member;
  120. this.NameImpl = null;
  121. this.PositionImpl = -1; // since parameter positions are zero-based, return type pos is -1
  122. this.AttrsImpl = ParameterAttributes.Retval;
  123. this.marshalAs = marshalAs;
  124. }
  125. public override
  126. object DefaultValue {
  127. get {
  128. if (ClassImpl == typeof (Decimal) || ClassImpl == typeof (Decimal?)) {
  129. /* default values for decimals are encoded using a custom attribute */
  130. DecimalConstantAttribute[] attrs = (DecimalConstantAttribute[])GetCustomAttributes (typeof (DecimalConstantAttribute), false);
  131. if (attrs.Length > 0)
  132. return attrs [0].Value;
  133. } else if (ClassImpl == typeof (DateTime) || ClassImpl == typeof (DateTime?)) {
  134. /* default values for DateTime are encoded using a custom attribute */
  135. DateTimeConstantAttribute[] attrs = (DateTimeConstantAttribute[])GetCustomAttributes (typeof (DateTimeConstantAttribute), false);
  136. if (attrs.Length > 0)
  137. return attrs [0].Value;
  138. }
  139. return DefaultValueImpl;
  140. }
  141. }
  142. public override
  143. object RawDefaultValue {
  144. get {
  145. if (DefaultValue != null && DefaultValue.GetType ().IsEnum)
  146. return ((Enum)DefaultValue).GetValue ();
  147. /*FIXME right now DefaultValue doesn't throw for reflection-only assemblies. Change this once the former is fixed.*/
  148. return DefaultValue;
  149. }
  150. }
  151. public
  152. override
  153. int MetadataToken {
  154. get {
  155. if (MemberImpl is PropertyInfo) {
  156. PropertyInfo prop = (PropertyInfo)MemberImpl;
  157. MethodInfo mi = prop.GetGetMethod (true);
  158. if (mi == null)
  159. mi = prop.GetSetMethod (true);
  160. return mi.GetParametersInternal () [PositionImpl].MetadataToken;
  161. } else if (MemberImpl is MethodBase) {
  162. return GetMetadataToken ();
  163. }
  164. throw new ArgumentException ("Can't produce MetadataToken for member of type " + MemberImpl.GetType ());
  165. }
  166. }
  167. public
  168. override
  169. object[] GetCustomAttributes (bool inherit)
  170. {
  171. return MonoCustomAttrs.GetCustomAttributes (this, inherit);
  172. }
  173. public
  174. override
  175. object[] GetCustomAttributes (Type attributeType, bool inherit)
  176. {
  177. return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
  178. }
  179. internal object GetDefaultValueImpl (ParameterInfo pinfo)
  180. {
  181. FieldInfo field = typeof (ParameterInfo).GetField ("DefaultValueImpl", BindingFlags.Instance | BindingFlags.NonPublic);
  182. return field.GetValue (pinfo);
  183. }
  184. public
  185. override
  186. bool IsDefined( Type attributeType, bool inherit) {
  187. return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
  188. }
  189. public override IList<CustomAttributeData> GetCustomAttributesData () {
  190. return CustomAttributeData.GetCustomAttributes (this);
  191. }
  192. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  193. internal extern int GetMetadataToken ();
  194. public override Type[] GetOptionalCustomModifiers () => GetCustomModifiers (true);
  195. internal object[] GetPseudoCustomAttributes ()
  196. {
  197. int count = 0;
  198. if (IsIn)
  199. count ++;
  200. if (IsOut)
  201. count ++;
  202. if (IsOptional)
  203. count ++;
  204. if (marshalAs != null)
  205. count ++;
  206. if (count == 0)
  207. return null;
  208. object[] attrs = new object [count];
  209. count = 0;
  210. if (IsIn)
  211. attrs [count ++] = new InAttribute ();
  212. if (IsOut)
  213. attrs [count ++] = new OutAttribute ();
  214. if (IsOptional)
  215. attrs [count ++] = new OptionalAttribute ();
  216. if (marshalAs != null) {
  217. #if NETCORE
  218. throw new NotImplementedException ();
  219. #else
  220. attrs [count ++] = marshalAs.Copy ();
  221. #endif
  222. }
  223. return attrs;
  224. }
  225. internal CustomAttributeData[] GetPseudoCustomAttributesData ()
  226. {
  227. int count = 0;
  228. if (IsIn)
  229. count++;
  230. if (IsOut)
  231. count++;
  232. if (IsOptional)
  233. count++;
  234. if (marshalAs != null)
  235. count++;
  236. if (count == 0)
  237. return null;
  238. CustomAttributeData[] attrsData = new CustomAttributeData [count];
  239. count = 0;
  240. if (IsIn)
  241. attrsData [count++] = new CustomAttributeData ((typeof (InAttribute)).GetConstructor (Type.EmptyTypes));
  242. if (IsOut)
  243. attrsData [count++] = new CustomAttributeData ((typeof (OutAttribute)).GetConstructor (Type.EmptyTypes));
  244. if (IsOptional)
  245. attrsData [count++] = new CustomAttributeData ((typeof (OptionalAttribute)).GetConstructor (Type.EmptyTypes));
  246. if (marshalAs != null) {
  247. var ctorArgs = new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument (typeof (UnmanagedType), marshalAs.Value) };
  248. attrsData [count++] = new CustomAttributeData (
  249. (typeof (MarshalAsAttribute)).GetConstructor (new[] { typeof (UnmanagedType) }),
  250. ctorArgs,
  251. EmptyArray<CustomAttributeNamedArgument>.Value);//FIXME Get named params
  252. }
  253. return attrsData;
  254. }
  255. public override Type[] GetRequiredCustomModifiers () => GetCustomModifiers (false);
  256. public override bool HasDefaultValue {
  257. get {
  258. object defaultValue = DefaultValue;
  259. if (defaultValue == null)
  260. return true;
  261. if (defaultValue.GetType () == typeof(DBNull) || defaultValue.GetType () == typeof(Missing))
  262. return false;
  263. return true;
  264. }
  265. }
  266. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  267. internal extern Type[] GetTypeModifiers (bool optional);
  268. internal static ParameterInfo New (ParameterInfo pinfo, Type type, MemberInfo member, int position)
  269. {
  270. return new RuntimeParameterInfo (pinfo, type, member, position);
  271. }
  272. internal static ParameterInfo New (ParameterInfo pinfo, MemberInfo member)
  273. {
  274. return new RuntimeParameterInfo (pinfo, member);
  275. }
  276. internal static ParameterInfo New (Type type, MemberInfo member, MarshalAsAttribute marshalAs)
  277. {
  278. return new RuntimeParameterInfo (type, member, marshalAs);
  279. }
  280. private Type[] GetCustomModifiers (bool optional) => GetTypeModifiers (optional) ?? Type.EmptyTypes;
  281. }
  282. }