MonoGenericClass.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. //
  2. // System.Reflection.MonoGenericClass
  3. //
  4. // Sean MacIsaac ([email protected])
  5. // Paolo Molaro ([email protected])
  6. // Patrik Torstensson ([email protected])
  7. //
  8. // (C) 2001 Ximian, Inc.
  9. //
  10. //
  11. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining
  14. // a copy of this software and associated documentation files (the
  15. // "Software"), to deal in the Software without restriction, including
  16. // without limitation the rights to use, copy, modify, merge, publish,
  17. // distribute, sublicense, and/or sell copies of the Software, and to
  18. // permit persons to whom the Software is furnished to do so, subject to
  19. // the following conditions:
  20. //
  21. // The above copyright notice and this permission notice shall be
  22. // included in all copies or substantial portions of the Software.
  23. //
  24. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  28. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  29. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  30. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31. //
  32. using System.Reflection;
  33. using System.Reflection.Emit;
  34. using System.Collections;
  35. using System.Runtime.CompilerServices;
  36. using System.Globalization;
  37. using System.Runtime.Serialization;
  38. #if NET_2_0 || BOOTSTRAP_NET_2_0
  39. namespace System.Reflection
  40. {
  41. /*
  42. * MonoGenericClass represents an instantiation of a generic TypeBuilder. MS
  43. * calls this class TypeBuilderInstantiation (a much better name). MS returns
  44. * NotImplementedException for many of the methods but we can't do that as gmcs
  45. * depends on them.
  46. */
  47. internal class MonoGenericClass : MonoType
  48. {
  49. #region Keep in sync with object-internals.h
  50. #pragma warning disable 649
  51. internal TypeBuilder generic_type;
  52. Type[] type_arguments;
  53. bool initialized;
  54. #pragma warning restore 649
  55. #endregion
  56. Hashtable fields, ctors, methods;
  57. int event_count;
  58. internal MonoGenericClass ()
  59. : base (null)
  60. {
  61. // this should not be used
  62. throw new InvalidOperationException ();
  63. }
  64. internal MonoGenericClass (TypeBuilder tb, Type[] args) : base (null)
  65. {
  66. this.generic_type = tb;
  67. this.type_arguments = args;
  68. }
  69. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  70. extern void initialize (MethodInfo[] methods, ConstructorInfo[] ctors, FieldInfo[] fields, PropertyInfo[] properties, EventInfo[] events);
  71. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  72. extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
  73. private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
  74. BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
  75. void initialize ()
  76. {
  77. if (initialized)
  78. return;
  79. MonoGenericClass parent = GetParentType () as MonoGenericClass;
  80. if (parent != null)
  81. parent.initialize ();
  82. EventInfo[] events = generic_type.GetEvents_internal (flags);
  83. event_count = events.Length;
  84. initialize (generic_type.GetMethods (flags),
  85. generic_type.GetConstructorsInternal (flags),
  86. generic_type.GetFields (flags),
  87. generic_type.GetProperties (flags),
  88. events);
  89. initialized = true;
  90. }
  91. Type GetParentType ()
  92. {
  93. return InflateType (generic_type.BaseType);
  94. }
  95. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  96. private extern Type InflateType_internal (Type type);
  97. internal Type InflateType (Type type)
  98. {
  99. if (type == null)
  100. return null;
  101. if (!type.IsGenericParameter && !type.ContainsGenericParameters)
  102. return type;
  103. return InflateType_internal (type);
  104. }
  105. public override Type BaseType {
  106. get {
  107. Type parent = GetParentType ();
  108. return parent != null ? parent : generic_type.BaseType;
  109. }
  110. }
  111. Type[] GetInterfacesInternal ()
  112. {
  113. if (generic_type.interfaces == null)
  114. return new Type [0];
  115. Type[] res = new Type [generic_type.interfaces.Length];
  116. for (int i = 0; i < res.Length; ++i)
  117. res [i] = InflateType (generic_type.interfaces [i]);
  118. return res;
  119. }
  120. public override Type[] GetInterfaces ()
  121. {
  122. if (!generic_type.IsCompilerContext)
  123. throw new NotSupportedException ();
  124. return GetInterfacesInternal ();
  125. }
  126. protected override bool IsValueTypeImpl ()
  127. {
  128. return generic_type.IsValueType;
  129. }
  130. internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
  131. {
  132. initialize ();
  133. if (!(fromNoninstanciated is MethodBuilder))
  134. throw new InvalidOperationException ("Inflating non MethodBuilder objects is not supported: " + fromNoninstanciated.GetType ());
  135. if (fromNoninstanciated is MethodBuilder) {
  136. MethodBuilder mb = (MethodBuilder)fromNoninstanciated;
  137. // FIXME: We can't yet handle creating generic instantiations of
  138. // MethodOnTypeBuilderInst objects
  139. // Also, mono_image_get_method_on_inst_token () can't handle generic
  140. // methods
  141. if (!mb.IsGenericMethodDefinition) {
  142. if (methods == null)
  143. methods = new Hashtable ();
  144. if (!methods.ContainsKey (mb))
  145. methods [mb] = new MethodOnTypeBuilderInst (this, mb);
  146. return (MethodInfo)methods [mb];
  147. }
  148. }
  149. return GetCorrespondingInflatedMethod (fromNoninstanciated);
  150. }
  151. internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
  152. {
  153. initialize ();
  154. if (!(fromNoninstanciated is ConstructorBuilder))
  155. throw new InvalidOperationException ("Inflating non ConstructorBuilder objects is not supported: " + fromNoninstanciated.GetType ());
  156. ConstructorBuilder cb = (ConstructorBuilder)fromNoninstanciated;
  157. if (ctors == null)
  158. ctors = new Hashtable ();
  159. if (!ctors.ContainsKey (cb))
  160. ctors [cb] = new ConstructorOnTypeBuilderInst (this, cb);
  161. return (ConstructorInfo)ctors [cb];
  162. }
  163. internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
  164. {
  165. initialize ();
  166. if (!(fromNoninstanciated is FieldBuilder))
  167. throw new InvalidOperationException ("Inflating non FieldBuilder objects is not supported: " + fromNoninstanciated.GetType ());
  168. FieldBuilder fb = (FieldBuilder)fromNoninstanciated;
  169. if (fields == null)
  170. fields = new Hashtable ();
  171. if (!fields.ContainsKey (fb))
  172. fields [fb] = new FieldOnTypeBuilderInst (this, fb);
  173. return (FieldInfo)fields [fb];
  174. }
  175. public override MethodInfo[] GetMethods (BindingFlags bf)
  176. {
  177. if (!generic_type.IsCompilerContext)
  178. throw new NotSupportedException ();
  179. ArrayList l = new ArrayList ();
  180. //
  181. // Walk up our class hierarchy and retrieve methods from our
  182. // parent classes.
  183. //
  184. Type current_type = this;
  185. do {
  186. MonoGenericClass gi = current_type as MonoGenericClass;
  187. if (gi != null)
  188. l.AddRange (gi.GetMethodsInternal (bf, this));
  189. else if (current_type is TypeBuilder)
  190. l.AddRange (current_type.GetMethods (bf));
  191. else {
  192. // If we encounter a `MonoType', its
  193. // GetMethodsByName() will return all the methods
  194. // from its parent type(s), so we can stop here.
  195. MonoType mt = (MonoType) current_type;
  196. l.AddRange (mt.GetMethodsByName (null, bf, false, this));
  197. break;
  198. }
  199. if ((bf & BindingFlags.DeclaredOnly) != 0)
  200. break;
  201. current_type = current_type.BaseType;
  202. } while (current_type != null);
  203. MethodInfo[] result = new MethodInfo [l.Count];
  204. l.CopyTo (result);
  205. return result;
  206. }
  207. MethodInfo[] GetMethodsInternal (BindingFlags bf, MonoGenericClass reftype)
  208. {
  209. if (generic_type.num_methods == 0)
  210. return new MethodInfo [0];
  211. ArrayList l = new ArrayList ();
  212. bool match;
  213. MethodAttributes mattrs;
  214. MethodInfo accessor;
  215. initialize ();
  216. for (int i = 0; i < generic_type.num_methods; ++i) {
  217. MethodInfo c = generic_type.methods [i];
  218. match = false;
  219. mattrs = c.Attributes;
  220. if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
  221. if ((bf & BindingFlags.Public) != 0)
  222. match = true;
  223. } else {
  224. if ((bf & BindingFlags.NonPublic) != 0)
  225. match = true;
  226. }
  227. if (!match)
  228. continue;
  229. match = false;
  230. if ((mattrs & MethodAttributes.Static) != 0) {
  231. if ((bf & BindingFlags.Static) != 0)
  232. match = true;
  233. } else {
  234. if ((bf & BindingFlags.Instance) != 0)
  235. match = true;
  236. }
  237. if (!match)
  238. continue;
  239. c = TypeBuilder.GetMethod (this, c);
  240. l.Add (c);
  241. }
  242. MethodInfo[] result = new MethodInfo [l.Count];
  243. l.CopyTo (result);
  244. return result;
  245. }
  246. public override ConstructorInfo[] GetConstructors (BindingFlags bf)
  247. {
  248. if (!generic_type.IsCompilerContext)
  249. throw new NotSupportedException ();
  250. ArrayList l = new ArrayList ();
  251. Type current_type = this;
  252. do {
  253. MonoGenericClass gi = current_type as MonoGenericClass;
  254. if (gi != null)
  255. l.AddRange (gi.GetConstructorsInternal (bf, this));
  256. else if (current_type is TypeBuilder)
  257. l.AddRange (current_type.GetConstructors (bf));
  258. else {
  259. MonoType mt = (MonoType) current_type;
  260. l.AddRange (mt.GetConstructors_internal (bf, this));
  261. break;
  262. }
  263. if ((bf & BindingFlags.DeclaredOnly) != 0)
  264. break;
  265. current_type = current_type.BaseType;
  266. } while (current_type != null);
  267. ConstructorInfo[] result = new ConstructorInfo [l.Count];
  268. l.CopyTo (result);
  269. return result;
  270. }
  271. ConstructorInfo[] GetConstructorsInternal (BindingFlags bf, MonoGenericClass reftype)
  272. {
  273. if (generic_type.ctors == null)
  274. return new ConstructorInfo [0];
  275. ArrayList l = new ArrayList ();
  276. bool match;
  277. MethodAttributes mattrs;
  278. initialize ();
  279. for (int i = 0; i < generic_type.ctors.Length; i++) {
  280. ConstructorInfo c = generic_type.ctors [i];
  281. match = false;
  282. mattrs = c.Attributes;
  283. if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
  284. if ((bf & BindingFlags.Public) != 0)
  285. match = true;
  286. } else {
  287. if ((bf & BindingFlags.NonPublic) != 0)
  288. match = true;
  289. }
  290. if (!match)
  291. continue;
  292. match = false;
  293. if ((mattrs & MethodAttributes.Static) != 0) {
  294. if ((bf & BindingFlags.Static) != 0)
  295. match = true;
  296. } else {
  297. if ((bf & BindingFlags.Instance) != 0)
  298. match = true;
  299. }
  300. if (!match)
  301. continue;
  302. l.Add (TypeBuilder.GetConstructor (this, c));
  303. }
  304. ConstructorInfo[] result = new ConstructorInfo [l.Count];
  305. l.CopyTo (result);
  306. return result;
  307. }
  308. public override FieldInfo[] GetFields (BindingFlags bf)
  309. {
  310. if (!generic_type.IsCompilerContext)
  311. throw new NotSupportedException ();
  312. ArrayList l = new ArrayList ();
  313. Type current_type = this;
  314. do {
  315. MonoGenericClass gi = current_type as MonoGenericClass;
  316. if (gi != null)
  317. l.AddRange (gi.GetFieldsInternal (bf, this));
  318. else if (current_type is TypeBuilder)
  319. l.AddRange (current_type.GetFields (bf));
  320. else {
  321. MonoType mt = (MonoType) current_type;
  322. l.AddRange (mt.GetFields_internal (bf, this));
  323. break;
  324. }
  325. if ((bf & BindingFlags.DeclaredOnly) != 0)
  326. break;
  327. current_type = current_type.BaseType;
  328. } while (current_type != null);
  329. FieldInfo[] result = new FieldInfo [l.Count];
  330. l.CopyTo (result);
  331. return result;
  332. }
  333. FieldInfo[] GetFieldsInternal (BindingFlags bf, MonoGenericClass reftype)
  334. {
  335. if (generic_type.num_fields == 0)
  336. return new FieldInfo [0];
  337. ArrayList l = new ArrayList ();
  338. bool match;
  339. FieldAttributes fattrs;
  340. initialize ();
  341. for (int i = 0; i < generic_type.num_fields; i++) {
  342. FieldInfo c = generic_type.fields [i];
  343. match = false;
  344. fattrs = c.Attributes;
  345. if ((fattrs & FieldAttributes.FieldAccessMask) == FieldAttributes.Public) {
  346. if ((bf & BindingFlags.Public) != 0)
  347. match = true;
  348. } else {
  349. if ((bf & BindingFlags.NonPublic) != 0)
  350. match = true;
  351. }
  352. if (!match)
  353. continue;
  354. match = false;
  355. if ((fattrs & FieldAttributes.Static) != 0) {
  356. if ((bf & BindingFlags.Static) != 0)
  357. match = true;
  358. } else {
  359. if ((bf & BindingFlags.Instance) != 0)
  360. match = true;
  361. }
  362. if (!match)
  363. continue;
  364. l.Add (TypeBuilder.GetField (this, c));
  365. }
  366. FieldInfo[] result = new FieldInfo [l.Count];
  367. l.CopyTo (result);
  368. return result;
  369. }
  370. public override PropertyInfo[] GetProperties (BindingFlags bf)
  371. {
  372. if (!generic_type.IsCompilerContext)
  373. throw new NotSupportedException ();
  374. ArrayList l = new ArrayList ();
  375. Type current_type = this;
  376. do {
  377. MonoGenericClass gi = current_type as MonoGenericClass;
  378. if (gi != null)
  379. l.AddRange (gi.GetPropertiesInternal (bf, this));
  380. else if (current_type is TypeBuilder)
  381. l.AddRange (current_type.GetProperties (bf));
  382. else {
  383. MonoType mt = (MonoType) current_type;
  384. l.AddRange (mt.GetPropertiesByName (null, bf, false, this));
  385. break;
  386. }
  387. if ((bf & BindingFlags.DeclaredOnly) != 0)
  388. break;
  389. current_type = current_type.BaseType;
  390. } while (current_type != null);
  391. PropertyInfo[] result = new PropertyInfo [l.Count];
  392. l.CopyTo (result);
  393. return result;
  394. }
  395. PropertyInfo[] GetPropertiesInternal (BindingFlags bf, MonoGenericClass reftype)
  396. {
  397. if (generic_type.properties == null)
  398. return new PropertyInfo [0];
  399. ArrayList l = new ArrayList ();
  400. bool match;
  401. MethodAttributes mattrs;
  402. MethodInfo accessor;
  403. initialize ();
  404. foreach (PropertyInfo pinfo in generic_type.properties) {
  405. match = false;
  406. accessor = pinfo.GetGetMethod (true);
  407. if (accessor == null)
  408. accessor = pinfo.GetSetMethod (true);
  409. if (accessor == null)
  410. continue;
  411. mattrs = accessor.Attributes;
  412. if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
  413. if ((bf & BindingFlags.Public) != 0)
  414. match = true;
  415. } else {
  416. if ((bf & BindingFlags.NonPublic) != 0)
  417. match = true;
  418. }
  419. if (!match)
  420. continue;
  421. match = false;
  422. if ((mattrs & MethodAttributes.Static) != 0) {
  423. if ((bf & BindingFlags.Static) != 0)
  424. match = true;
  425. } else {
  426. if ((bf & BindingFlags.Instance) != 0)
  427. match = true;
  428. }
  429. if (!match)
  430. continue;
  431. l.Add (new PropertyOnTypeBuilderInst (reftype, pinfo));
  432. }
  433. PropertyInfo[] result = new PropertyInfo [l.Count];
  434. l.CopyTo (result);
  435. return result;
  436. }
  437. public override EventInfo[] GetEvents (BindingFlags bf)
  438. {
  439. if (!generic_type.IsCompilerContext)
  440. throw new NotSupportedException ();
  441. ArrayList l = new ArrayList ();
  442. Type current_type = this;
  443. do {
  444. MonoGenericClass gi = current_type as MonoGenericClass;
  445. if (gi != null)
  446. l.AddRange (gi.GetEventsInternal (bf, this));
  447. else if (current_type is TypeBuilder)
  448. l.AddRange (current_type.GetEvents (bf));
  449. else {
  450. MonoType mt = (MonoType) current_type;
  451. l.AddRange (mt.GetEvents (bf));
  452. break;
  453. }
  454. if ((bf & BindingFlags.DeclaredOnly) != 0)
  455. break;
  456. current_type = current_type.BaseType;
  457. } while (current_type != null);
  458. EventInfo[] result = new EventInfo [l.Count];
  459. l.CopyTo (result);
  460. return result;
  461. }
  462. EventInfo[] GetEventsInternal (BindingFlags bf, MonoGenericClass reftype) {
  463. if (generic_type.events == null)
  464. return new EventInfo [0];
  465. initialize ();
  466. ArrayList l = new ArrayList ();
  467. bool match;
  468. MethodAttributes mattrs;
  469. MethodInfo accessor;
  470. for (int i = 0; i < event_count; ++i) {
  471. EventBuilder ev = generic_type.events [i];
  472. match = false;
  473. accessor = ev.add_method;
  474. if (accessor == null)
  475. accessor = ev.remove_method;
  476. if (accessor == null)
  477. continue;
  478. mattrs = accessor.Attributes;
  479. if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
  480. if ((bf & BindingFlags.Public) != 0)
  481. match = true;
  482. } else {
  483. if ((bf & BindingFlags.NonPublic) != 0)
  484. match = true;
  485. }
  486. if (!match)
  487. continue;
  488. match = false;
  489. if ((mattrs & MethodAttributes.Static) != 0) {
  490. if ((bf & BindingFlags.Static) != 0)
  491. match = true;
  492. } else {
  493. if ((bf & BindingFlags.Instance) != 0)
  494. match = true;
  495. }
  496. if (!match)
  497. continue;
  498. l.Add (new EventOnTypeBuilderInst (this, ev));
  499. }
  500. EventInfo[] result = new EventInfo [l.Count];
  501. l.CopyTo (result);
  502. return result;
  503. }
  504. public override Type[] GetNestedTypes (BindingFlags bf)
  505. {
  506. return generic_type.GetNestedTypes (bf);
  507. }
  508. public override bool IsAssignableFrom (Type c)
  509. {
  510. if (c == this)
  511. return true;
  512. Type[] interfaces = GetInterfacesInternal ();
  513. if (c.IsInterface) {
  514. if (interfaces == null)
  515. return false;
  516. foreach (Type t in interfaces)
  517. if (c.IsAssignableFrom (t))
  518. return true;
  519. return false;
  520. }
  521. Type parent = GetParentType ();
  522. if (parent == null)
  523. return c == typeof (object);
  524. else
  525. return c.IsAssignableFrom (parent);
  526. }
  527. }
  528. }
  529. #endif