CustomAttributeBuilder.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. //
  2. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining
  5. // a copy of this software and associated documentation files (the
  6. // "Software"), to deal in the Software without restriction, including
  7. // without limitation the rights to use, copy, modify, merge, publish,
  8. // distribute, sublicense, and/or sell copies of the Software, and to
  9. // permit persons to whom the Software is furnished to do so, subject to
  10. // the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be
  13. // included in all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. //
  23. //
  24. // System.Reflection.Emit/CustomAttributeBuilder.cs
  25. //
  26. // Author:
  27. // Paolo Molaro ([email protected])
  28. //
  29. // (C) 2001 Ximian, Inc. http://www.ximian.com
  30. //
  31. #if MONO_FEATURE_SRE
  32. using System;
  33. using System.Reflection;
  34. using System.Reflection.Emit;
  35. using System.Runtime.CompilerServices;
  36. using System.Runtime.InteropServices;
  37. namespace System.Reflection.Emit {
  38. #if !MOBILE
  39. [ComVisible (true)]
  40. [ComDefaultInterface (typeof (_CustomAttributeBuilder))]
  41. [ClassInterface (ClassInterfaceType.None)]
  42. partial class CustomAttributeBuilder : _CustomAttributeBuilder
  43. {
  44. void _CustomAttributeBuilder.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
  45. {
  46. throw new NotImplementedException ();
  47. }
  48. void _CustomAttributeBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
  49. {
  50. throw new NotImplementedException ();
  51. }
  52. void _CustomAttributeBuilder.GetTypeInfoCount (out uint pcTInfo)
  53. {
  54. throw new NotImplementedException ();
  55. }
  56. void _CustomAttributeBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
  57. {
  58. throw new NotImplementedException ();
  59. }
  60. }
  61. #endif
  62. [StructLayout (LayoutKind.Sequential)]
  63. public partial class CustomAttributeBuilder {
  64. ConstructorInfo ctor;
  65. byte[] data;
  66. object [] args;
  67. PropertyInfo [] namedProperties;
  68. object [] propertyValues;
  69. FieldInfo [] namedFields;
  70. object [] fieldValues;
  71. internal ConstructorInfo Ctor {
  72. get {return ctor;}
  73. }
  74. internal byte[] Data {
  75. get {return data;}
  76. }
  77. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  78. static extern byte[] GetBlob(Assembly asmb, ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues);
  79. internal object Invoke ()
  80. {
  81. object result = ctor.Invoke (args);
  82. for (int i=0; i < namedFields.Length; i++)
  83. namedFields [i].SetValue (result, fieldValues [i]);
  84. for (int i=0; i < namedProperties.Length; i++)
  85. namedProperties [i].SetValue (result, propertyValues [i]);
  86. return result;
  87. }
  88. internal CustomAttributeBuilder( ConstructorInfo con, byte[] binaryAttribute) {
  89. if (con == null)
  90. throw new ArgumentNullException ("con");
  91. if (binaryAttribute == null)
  92. throw new ArgumentNullException ("binaryAttribute");
  93. ctor = con;
  94. data = (byte[])binaryAttribute.Clone ();
  95. /* should we check that the user supplied data is correct? */
  96. }
  97. public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs)
  98. {
  99. Initialize (con, constructorArgs, new PropertyInfo [0], new object [0],
  100. new FieldInfo [0], new object [0]);
  101. }
  102. public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
  103. FieldInfo[] namedFields, object[] fieldValues)
  104. {
  105. Initialize (con, constructorArgs, new PropertyInfo [0], new object [0],
  106. namedFields, fieldValues);
  107. }
  108. public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
  109. PropertyInfo[] namedProperties, object[] propertyValues)
  110. {
  111. Initialize (con, constructorArgs, namedProperties, propertyValues, new FieldInfo [0],
  112. new object [0]);
  113. }
  114. public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
  115. PropertyInfo[] namedProperties, object[] propertyValues,
  116. FieldInfo[] namedFields, object[] fieldValues)
  117. {
  118. Initialize (con, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues);
  119. }
  120. private bool IsValidType (Type t)
  121. {
  122. /* FIXME: Add more checks */
  123. if (t.IsArray && t.GetArrayRank () > 1)
  124. return false;
  125. if (t is TypeBuilder && t.IsEnum) {
  126. // Check that the enum is properly constructed, the unmanaged code
  127. // depends on this
  128. Enum.GetUnderlyingType (t);
  129. }
  130. if (t.IsClass && !(t.IsArray || t == typeof (object) || t == typeof (Type) || t == typeof (string) || t.Assembly.GetName ().Name == "mscorlib"))
  131. return false;
  132. if (t.IsValueType && !(t.IsPrimitive || t.IsEnum || ((t.Assembly is AssemblyBuilder) && t.Assembly.GetName ().Name == "mscorlib")))
  133. return false;
  134. return true;
  135. }
  136. private bool IsValidParam (object o, Type paramType)
  137. {
  138. Type t = o.GetType ();
  139. if (!IsValidType (t))
  140. return false;
  141. if (paramType == typeof (object)) {
  142. if (t.IsArray && t.GetArrayRank () == 1)
  143. return IsValidType (t.GetElementType ());
  144. if (!t.IsPrimitive && !typeof (Type).IsAssignableFrom (t) && t != typeof (string) && !t.IsEnum)
  145. return false;
  146. }
  147. return true;
  148. }
  149. static bool IsValidValue (Type type, object value) {
  150. if (type.IsValueType && value == null)
  151. return false;
  152. if (type.IsArray && type.GetElementType ().IsValueType) {
  153. foreach (var v in (Array)value) {
  154. if (v == null)
  155. return false;
  156. }
  157. }
  158. return true;
  159. }
  160. private void Initialize (ConstructorInfo con, object [] constructorArgs,
  161. PropertyInfo [] namedProperties, object [] propertyValues,
  162. FieldInfo [] namedFields, object [] fieldValues)
  163. {
  164. ctor = con;
  165. args = constructorArgs;
  166. this.namedProperties = namedProperties;
  167. this.propertyValues = propertyValues;
  168. this.namedFields = namedFields;
  169. this.fieldValues = fieldValues;
  170. if (con == null)
  171. throw new ArgumentNullException ("con");
  172. if (constructorArgs == null)
  173. throw new ArgumentNullException ("constructorArgs");
  174. if (namedProperties == null)
  175. throw new ArgumentNullException ("namedProperties");
  176. if (propertyValues == null)
  177. throw new ArgumentNullException ("propertyValues");
  178. if (namedFields == null)
  179. throw new ArgumentNullException ("namedFields");
  180. if (fieldValues == null)
  181. throw new ArgumentNullException ("fieldValues");
  182. if (con.GetParametersCount () != constructorArgs.Length)
  183. throw new ArgumentException ("Parameter count does not match " +
  184. "passed in argument value count.");
  185. if (namedProperties.Length != propertyValues.Length)
  186. throw new ArgumentException ("Array lengths must be the same.",
  187. "namedProperties, propertyValues");
  188. if (namedFields.Length != fieldValues.Length)
  189. throw new ArgumentException ("Array lengths must be the same.",
  190. "namedFields, fieldValues");
  191. if ((con.Attributes & MethodAttributes.Static) == MethodAttributes.Static ||
  192. (con.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
  193. throw new ArgumentException ("Cannot have private or static constructor.");
  194. Type atype = ctor.DeclaringType;
  195. int i;
  196. i = 0;
  197. foreach (FieldInfo fi in namedFields) {
  198. Type t = fi.DeclaringType;
  199. if ((atype != t) && (!t.IsSubclassOf (atype)) && (!atype.IsSubclassOf (t)))
  200. throw new ArgumentException ("Field '" + fi.Name + "' does not belong to the same class as the constructor");
  201. if (!IsValidType (fi.FieldType))
  202. throw new ArgumentException ("Field '" + fi.Name + "' does not have a valid type.");
  203. if (!IsValidValue (fi.FieldType, fieldValues [i]))
  204. throw new ArgumentException ("Field " + fi.Name + " is not a valid value.");
  205. // FIXME: Check enums and TypeBuilders as well
  206. if (fieldValues [i] != null)
  207. // IsEnum does not seem to work on TypeBuilders
  208. if (!(fi.FieldType is TypeBuilder) && !fi.FieldType.IsEnum && !fi.FieldType.IsInstanceOfType (fieldValues [i])) {
  209. //
  210. // mcs allways uses object[] for array types and
  211. // MS.NET allows this
  212. //
  213. if (!fi.FieldType.IsArray)
  214. throw new ArgumentException ("Value of field '" + fi.Name + "' does not match field type: " + fi.FieldType);
  215. }
  216. i ++;
  217. }
  218. i = 0;
  219. foreach (PropertyInfo pi in namedProperties) {
  220. if (!pi.CanWrite)
  221. throw new ArgumentException ("Property '" + pi.Name + "' does not have a setter.");
  222. Type t = pi.DeclaringType;
  223. if ((atype != t) && (!t.IsSubclassOf (atype)) && (!atype.IsSubclassOf (t)))
  224. throw new ArgumentException ("Property '" + pi.Name + "' does not belong to the same class as the constructor");
  225. if (!IsValidType (pi.PropertyType))
  226. throw new ArgumentException ("Property '" + pi.Name + "' does not have a valid type.");
  227. if (!IsValidValue (pi.PropertyType, propertyValues [i]))
  228. throw new ArgumentException ("Property " + pi.Name + " is not a valid value.");
  229. if (propertyValues [i] != null) {
  230. if (!(pi.PropertyType is TypeBuilder) && !pi.PropertyType.IsEnum && !pi.PropertyType.IsInstanceOfType (propertyValues [i]))
  231. if (!pi.PropertyType.IsArray)
  232. throw new ArgumentException ("Value of property '" + pi.Name + "' does not match property type: " + pi.PropertyType + " -> " + propertyValues [i]);
  233. }
  234. i ++;
  235. }
  236. i = 0;
  237. foreach (ParameterInfo pi in GetParameters (con)) {
  238. if (pi != null) {
  239. Type paramType = pi.ParameterType;
  240. if (!IsValidType (paramType))
  241. throw new ArgumentException ("Parameter " + i + " does not have a valid type.");
  242. if (!IsValidValue (paramType, constructorArgs [i]))
  243. throw new ArgumentException ("Parameter " + i + " is not a valid value.");
  244. if (constructorArgs [i] != null) {
  245. if (!(paramType is TypeBuilder) && !paramType.IsEnum && !paramType.IsInstanceOfType (constructorArgs [i]))
  246. if (!paramType.IsArray)
  247. throw new ArgumentException ("Value of argument " + i + " does not match parameter type: " + paramType + " -> " + constructorArgs [i]);
  248. if (!IsValidParam (constructorArgs [i], paramType))
  249. throw new ArgumentException ("Cannot emit a CustomAttribute with argument of type " + constructorArgs [i].GetType () + ".");
  250. }
  251. }
  252. i ++;
  253. }
  254. data = GetBlob (atype.Assembly, con, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues);
  255. }
  256. /* helper methods */
  257. internal static int decode_len (byte[] data, int pos, out int rpos) {
  258. int len = 0;
  259. if ((data [pos] & 0x80) == 0) {
  260. len = (int)(data [pos++] & 0x7f);
  261. } else if ((data [pos] & 0x40) == 0) {
  262. len = ((data [pos] & 0x3f) << 8) + data [pos + 1];
  263. pos += 2;
  264. } else {
  265. len = ((data [pos] & 0x1f) << 24) + (data [pos + 1] << 16) + (data [pos + 2] << 8) + data [pos + 3];
  266. pos += 4;
  267. }
  268. rpos = pos;
  269. return len;
  270. }
  271. internal static string string_from_bytes (byte[] data, int pos, int len)
  272. {
  273. return System.Text.Encoding.UTF8.GetString(data, pos, len);
  274. }
  275. internal string string_arg ()
  276. {
  277. int pos = 2;
  278. int len = decode_len (data, pos, out pos);
  279. return string_from_bytes (data, pos, len);
  280. }
  281. internal static UnmanagedMarshal get_umarshal (CustomAttributeBuilder customBuilder, bool is_field) {
  282. byte[] data = customBuilder.Data;
  283. UnmanagedType subtype = (UnmanagedType)0x50; /* NATIVE_MAX */
  284. int sizeConst = -1;
  285. int sizeParamIndex = -1;
  286. bool hasSize = false;
  287. int value;
  288. int utype; /* the (stupid) ctor takes a short or an enum ... */
  289. string marshalTypeName = null;
  290. Type marshalTypeRef = null;
  291. string marshalCookie = String.Empty;
  292. utype = (int)data [2];
  293. utype |= ((int)data [3]) << 8;
  294. string first_type_name = GetParameters (customBuilder.Ctor) [0].ParameterType.FullName;
  295. int pos = 6;
  296. if (first_type_name == "System.Int16")
  297. pos = 4;
  298. int nnamed = (int)data [pos++];
  299. nnamed |= ((int)data [pos++]) << 8;
  300. for (int i = 0; i < nnamed; ++i) {
  301. int paramType; // What is this ?
  302. /* Skip field/property signature */
  303. pos ++;
  304. /* Read type */
  305. paramType = ((int)data [pos++]);
  306. if (paramType == 0x55) {
  307. /* enums, the value is preceeded by the type */
  308. int len2 = decode_len (data, pos, out pos);
  309. string_from_bytes (data, pos, len2);
  310. pos += len2;
  311. }
  312. int len = decode_len (data, pos, out pos);
  313. string named_name = string_from_bytes (data, pos, len);
  314. pos += len;
  315. switch (named_name) {
  316. case "ArraySubType":
  317. value = (int)data [pos++];
  318. value |= ((int)data [pos++]) << 8;
  319. value |= ((int)data [pos++]) << 16;
  320. value |= ((int)data [pos++]) << 24;
  321. subtype = (UnmanagedType)value;
  322. break;
  323. case "SizeConst":
  324. value = (int)data [pos++];
  325. value |= ((int)data [pos++]) << 8;
  326. value |= ((int)data [pos++]) << 16;
  327. value |= ((int)data [pos++]) << 24;
  328. sizeConst = value;
  329. hasSize = true;
  330. break;
  331. case "SafeArraySubType":
  332. value = (int)data[pos++];
  333. value |= ((int)data[pos++]) << 8;
  334. value |= ((int)data[pos++]) << 16;
  335. value |= ((int)data[pos++]) << 24;
  336. subtype = (UnmanagedType)value;
  337. break;
  338. case "IidParameterIndex":
  339. pos += 4;
  340. break;
  341. case "SafeArrayUserDefinedSubType":
  342. len = decode_len (data, pos, out pos);
  343. string_from_bytes (data, pos, len);
  344. pos += len;
  345. break;
  346. case "SizeParamIndex":
  347. value = (int)data [pos++];
  348. value |= ((int)data [pos++]) << 8;
  349. sizeParamIndex = value;
  350. hasSize = true;
  351. break;
  352. case "MarshalType":
  353. len = decode_len (data, pos, out pos);
  354. marshalTypeName = string_from_bytes (data, pos, len);
  355. pos += len;
  356. break;
  357. case "MarshalTypeRef":
  358. len = decode_len (data, pos, out pos);
  359. marshalTypeName = string_from_bytes (data, pos, len);
  360. marshalTypeRef = Type.GetType (marshalTypeName);
  361. pos += len;
  362. break;
  363. case "MarshalCookie":
  364. len = decode_len (data, pos, out pos);
  365. marshalCookie = string_from_bytes (data, pos, len);
  366. pos += len;
  367. break;
  368. default:
  369. throw new Exception ("Unknown MarshalAsAttribute field: " + named_name);
  370. }
  371. }
  372. switch ((UnmanagedType)utype) {
  373. case UnmanagedType.LPArray:
  374. if (hasSize)
  375. return UnmanagedMarshal.DefineLPArrayInternal (subtype, sizeConst, sizeParamIndex);
  376. else
  377. return UnmanagedMarshal.DefineLPArray (subtype);
  378. #if FEATURE_COMINTEROP
  379. case UnmanagedType.SafeArray:
  380. return UnmanagedMarshal.DefineSafeArray (subtype);
  381. #endif
  382. case UnmanagedType.ByValArray:
  383. if (!is_field)
  384. throw new ArgumentException ("Specified unmanaged type is only valid on fields");
  385. return UnmanagedMarshal.DefineByValArray (sizeConst);
  386. case UnmanagedType.ByValTStr:
  387. return UnmanagedMarshal.DefineByValTStr (sizeConst);
  388. #if FEATURE_COMINTEROP
  389. case UnmanagedType.CustomMarshaler:
  390. return UnmanagedMarshal.DefineCustom (marshalTypeRef, marshalCookie, marshalTypeName, Guid.Empty);
  391. #endif
  392. default:
  393. return UnmanagedMarshal.DefineUnmanagedMarshal ((UnmanagedType)utype);
  394. }
  395. }
  396. static Type elementTypeToType (int elementType) {
  397. /* Partition II, section 23.1.16 */
  398. switch (elementType) {
  399. case 0x02:
  400. return typeof (bool);
  401. case 0x03:
  402. return typeof (char);
  403. case 0x04:
  404. return typeof (sbyte);
  405. case 0x05:
  406. return typeof (byte);
  407. case 0x06:
  408. return typeof (short);
  409. case 0x07:
  410. return typeof (ushort);
  411. case 0x08:
  412. return typeof (int);
  413. case 0x09:
  414. return typeof (uint);
  415. case 0x0a:
  416. return typeof (long);
  417. case 0x0b:
  418. return typeof (ulong);
  419. case 0x0c:
  420. return typeof (float);
  421. case 0x0d:
  422. return typeof (double);
  423. case 0x0e:
  424. return typeof (string);
  425. default:
  426. throw new Exception ("Unknown element type '" + elementType + "'");
  427. }
  428. }
  429. static object decode_cattr_value (Type t, byte[] data, int pos, out int rpos) {
  430. switch (Type.GetTypeCode (t)) {
  431. case TypeCode.String:
  432. if (data [pos] == 0xff) {
  433. rpos = pos + 1;
  434. return null;
  435. }
  436. int len = decode_len (data, pos, out pos);
  437. rpos = pos + len;
  438. return string_from_bytes (data, pos, len);
  439. case TypeCode.Int32:
  440. rpos = pos + 4;
  441. return data [pos] + (data [pos + 1] << 8) + (data [pos + 2] << 16) + (data [pos + 3] << 24);
  442. case TypeCode.Boolean:
  443. rpos = pos + 1;
  444. return (data [pos] == 0) ? false : true;
  445. case TypeCode.Object:
  446. int subtype = data [pos];
  447. pos += 1;
  448. if (subtype >= 0x02 && subtype <= 0x0e)
  449. return decode_cattr_value (elementTypeToType (subtype), data, pos, out rpos);
  450. else
  451. throw new Exception ("Subtype '" + subtype + "' of type object not yet handled in decode_cattr_value");
  452. default:
  453. throw new Exception ("FIXME: Type " + t + " not yet handled in decode_cattr_value.");
  454. }
  455. }
  456. internal struct CustomAttributeInfo {
  457. public ConstructorInfo ctor;
  458. public object[] ctorArgs;
  459. public string[] namedParamNames;
  460. public object[] namedParamValues;
  461. }
  462. internal static CustomAttributeInfo decode_cattr (CustomAttributeBuilder customBuilder) {
  463. byte[] data = customBuilder.Data;
  464. ConstructorInfo ctor = customBuilder.Ctor;
  465. int pos = 0;
  466. CustomAttributeInfo info = new CustomAttributeInfo ();
  467. // Prolog
  468. if (data.Length < 2)
  469. throw new Exception ("Custom attr length is only '" + data.Length + "'");
  470. if ((data [0] != 0x1) || (data [1] != 0x00))
  471. throw new Exception ("Prolog invalid");
  472. pos = 2;
  473. ParameterInfo [] pi = GetParameters (ctor);
  474. info.ctor = ctor;
  475. info.ctorArgs = new object [pi.Length];
  476. for (int i = 0; i < pi.Length; ++i)
  477. info.ctorArgs [i] = decode_cattr_value (pi [i].ParameterType, data, pos, out pos);
  478. int num_named = data [pos] + (data [pos + 1] * 256);
  479. pos += 2;
  480. info.namedParamNames = new string [num_named];
  481. info.namedParamValues = new object [num_named];
  482. for (int i = 0; i < num_named; ++i) {
  483. int named_type = data [pos++];
  484. int data_type = data [pos++];
  485. string enum_type_name = null;
  486. if (data_type == 0x55) {
  487. int len2 = decode_len (data, pos, out pos);
  488. enum_type_name = string_from_bytes (data, pos, len2);
  489. pos += len2;
  490. }
  491. int len = decode_len (data, pos, out pos);
  492. string name = string_from_bytes (data, pos, len);
  493. info.namedParamNames [i] = name;
  494. pos += len;
  495. if (named_type == 0x53) {
  496. /* Field */
  497. FieldInfo fi = ctor.DeclaringType.GetField (name, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);
  498. if (fi == null)
  499. throw new Exception ("Custom attribute type '" + ctor.DeclaringType + "' doesn't contain a field named '" + name + "'");
  500. object val = decode_cattr_value (fi.FieldType, data, pos, out pos);
  501. if (enum_type_name != null) {
  502. Type enumType = Type.GetType (enum_type_name);
  503. val = Enum.ToObject (enumType, val);
  504. }
  505. info.namedParamValues [i] = val;
  506. }
  507. else
  508. // FIXME:
  509. throw new Exception ("Unknown named type: " + named_type);
  510. }
  511. return info;
  512. }
  513. static ParameterInfo [] GetParameters (ConstructorInfo ctor)
  514. {
  515. ConstructorBuilder cb = ctor as ConstructorBuilder;
  516. if (cb != null)
  517. return cb.GetParametersInternal ();
  518. return ctor.GetParametersInternal ();
  519. }
  520. }
  521. }
  522. #endif