PageRenderTime 57ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/Runtime/Microsoft.Dynamic/Utils/ReflectionUtils.cs

http://github.com/IronLanguages/main
C# | 1924 lines | 1475 code | 315 blank | 134 comment | 421 complexity | df3aab61498b713c845676ba6b43ae56 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if FEATURE_METADATA_READER
  16. using Microsoft.Scripting.Metadata;
  17. #endif
  18. #if !FEATURE_TYPE_INFO
  19. using TypeInfo = System.Type;
  20. #endif
  21. using System;
  22. using System.Collections.Generic;
  23. using System.Collections.ObjectModel;
  24. using System.Diagnostics;
  25. using System.Linq;
  26. using System.Reflection;
  27. using System.Reflection.Emit;
  28. using System.Runtime.CompilerServices;
  29. using System.Security;
  30. using System.Text;
  31. using System.Runtime.InteropServices;
  32. using System.Dynamic;
  33. using System.Linq.Expressions;
  34. using Microsoft.Scripting.Generation;
  35. using Microsoft.Scripting.Runtime;
  36. using Microsoft.Scripting.Utils;
  37. #if WIN8 || WP75 || NETSTANDARD
  38. namespace System.Runtime.CompilerServices {
  39. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event)]
  40. public sealed class SpecialNameAttribute : Attribute {
  41. public SpecialNameAttribute() {
  42. }
  43. }
  44. }
  45. #endif
  46. #if WIN8
  47. namespace System {
  48. public enum TypeCode {
  49. Empty,
  50. Object,
  51. DBNull,
  52. Boolean,
  53. Char,
  54. SByte,
  55. Byte,
  56. Int16,
  57. UInt16,
  58. Int32,
  59. UInt32,
  60. Int64,
  61. UInt64,
  62. Single,
  63. Double,
  64. Decimal,
  65. DateTime,
  66. String = 18
  67. }
  68. }
  69. namespace System.Reflection {
  70. [Flags]
  71. public enum BindingFlags {
  72. /// <summary>Specifies that instance members are to be included in the search.</summary>
  73. Instance = 4,
  74. /// <summary>Specifies that static members are to be included in the search.</summary>
  75. Static = 8,
  76. /// <summary>Specifies that public members are to be included in the search.</summary>
  77. Public = 16,
  78. /// <summary>Specifies that non-public members are to be included in the search.</summary>
  79. NonPublic = 32
  80. }
  81. }
  82. #elif !CLR45
  83. namespace System.Reflection {
  84. public static class RuntimeReflectionExtensions {
  85. public static MethodInfo GetRuntimeBaseDefinition(this MethodInfo method) {
  86. return method.GetBaseDefinition();
  87. }
  88. public static IEnumerable<MethodInfo> GetRuntimeMethods(this Type type) {
  89. return type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
  90. }
  91. #if !FEATURE_GET_METHOD_INFO
  92. public static MethodInfo GetMethodInfo(this Delegate d) {
  93. return d.Method;
  94. }
  95. #endif
  96. #if !FEATURE_TYPE_INFO
  97. public static InterfaceMapping GetRuntimeInterfaceMap(this Type typeInfo, Type interfaceType) {
  98. return typeInfo.GetInterfaceMap(interfaceType);
  99. }
  100. #endif
  101. }
  102. }
  103. #endif
  104. namespace Microsoft.Scripting.Utils {
  105. // CF doesn't support DefaultParameterValue attribute. Define our own, but not in System.Runtime.InteropServices namespace as that would
  106. // make C# compiler emit the parameter's default value metadata not the attribute itself. The default value metadata are not accessible on CF.
  107. #if !FEATURE_DEFAULT_PARAMETER_VALUE
  108. /// <summary>
  109. /// The Default Parameter Value Attribute.
  110. /// </summary>
  111. public sealed class DefaultParameterValueAttribute : Attribute
  112. {
  113. private readonly object _value;
  114. public object Value
  115. {
  116. get { return _value; }
  117. }
  118. /// <summary>
  119. /// The constructor
  120. /// </summary>
  121. /// <param name="value">The value.</param>
  122. public DefaultParameterValueAttribute(object value)
  123. {
  124. _value = value;
  125. }
  126. }
  127. #if !ANDROID
  128. [AttributeUsage(AttributeTargets.Parameter, Inherited = false), ComVisible(true)]
  129. public sealed class OptionalAttribute : Attribute {
  130. }
  131. #endif
  132. #endif
  133. public static class ReflectionUtils {
  134. #region Accessibility
  135. public static BindingFlags AllMembers = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
  136. public static bool IsPublic(this PropertyInfo property) {
  137. return property.GetGetMethod(nonPublic: false) != null
  138. || property.GetSetMethod(nonPublic: false) != null;
  139. }
  140. public static bool IsStatic(this PropertyInfo property) {
  141. var getter = property.GetGetMethod(nonPublic: true);
  142. var setter = property.GetSetMethod(nonPublic: true);
  143. return getter != null && getter.IsStatic
  144. || setter != null && setter.IsStatic;
  145. }
  146. public static bool IsStatic(this EventInfo evnt) {
  147. var add = evnt.GetAddMethod(nonPublic: true);
  148. var remove = evnt.GetRemoveMethod(nonPublic: true);
  149. return add != null && add.IsStatic
  150. || remove != null && remove.IsStatic;
  151. }
  152. public static bool IsPrivate(this PropertyInfo property) {
  153. var getter = property.GetGetMethod(nonPublic: true);
  154. var setter = property.GetSetMethod(nonPublic: true);
  155. return (getter == null || getter.IsPrivate)
  156. && (setter == null || setter.IsPrivate);
  157. }
  158. public static bool IsPrivate(this EventInfo evnt) {
  159. var add = evnt.GetAddMethod(nonPublic: true);
  160. var remove = evnt.GetRemoveMethod(nonPublic: true);
  161. return (add == null || add.IsPrivate)
  162. && (remove == null || remove.IsPrivate);
  163. }
  164. private static bool MatchesFlags(ConstructorInfo member, BindingFlags flags) {
  165. return
  166. ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
  167. ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
  168. }
  169. private static bool MatchesFlags(MethodInfo member, BindingFlags flags) {
  170. return
  171. ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
  172. ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
  173. }
  174. private static bool MatchesFlags(FieldInfo member, BindingFlags flags) {
  175. return
  176. ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
  177. ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
  178. }
  179. private static bool MatchesFlags(PropertyInfo member, BindingFlags flags) {
  180. return
  181. ((member.IsPublic() ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
  182. ((member.IsStatic() ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
  183. }
  184. private static bool MatchesFlags(EventInfo member, BindingFlags flags) {
  185. var add = member.GetAddMethod();
  186. var remove = member.GetRemoveMethod();
  187. var raise = member.GetRaiseMethod();
  188. bool isPublic = add != null && add.IsPublic || remove != null && remove.IsPublic || raise != null && raise.IsPublic;
  189. bool isStatic = add != null && add.IsStatic || remove != null && remove.IsStatic || raise != null && raise.IsStatic;
  190. return
  191. ((isPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
  192. ((isStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
  193. }
  194. private static bool MatchesFlags(TypeInfo member, BindingFlags flags) {
  195. // Static/Instance are ignored
  196. return (((member.IsPublic || member.IsNestedPublic) ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0;
  197. }
  198. private static bool MatchesFlags(MemberInfo member, BindingFlags flags) {
  199. ConstructorInfo ctor;
  200. MethodInfo method;
  201. FieldInfo field;
  202. EventInfo evnt;
  203. PropertyInfo property;
  204. if ((method = member as MethodInfo) != null) {
  205. return MatchesFlags(method, flags);
  206. }
  207. if ((field = member as FieldInfo) != null) {
  208. return MatchesFlags(field, flags);
  209. }
  210. if ((ctor = member as ConstructorInfo) != null) {
  211. return MatchesFlags(ctor, flags);
  212. }
  213. if ((evnt = member as EventInfo) != null) {
  214. return MatchesFlags(evnt, flags);
  215. }
  216. if ((property = member as PropertyInfo) != null) {
  217. return MatchesFlags(property, flags);
  218. }
  219. return MatchesFlags((TypeInfo)member, flags);
  220. }
  221. private static IEnumerable<T> WithBindingFlags<T>(this IEnumerable<T> members, Func<T, BindingFlags, bool> matchFlags, BindingFlags flags)
  222. where T : MemberInfo {
  223. return members.Where(member => matchFlags(member, flags));
  224. }
  225. public static IEnumerable<MemberInfo> WithBindingFlags(this IEnumerable<MemberInfo> members, BindingFlags flags) {
  226. return members.WithBindingFlags(MatchesFlags, flags);
  227. }
  228. public static IEnumerable<MethodInfo> WithBindingFlags(this IEnumerable<MethodInfo> members, BindingFlags flags) {
  229. return members.WithBindingFlags(MatchesFlags, flags);
  230. }
  231. public static IEnumerable<ConstructorInfo> WithBindingFlags(this IEnumerable<ConstructorInfo> members, BindingFlags flags) {
  232. return members.WithBindingFlags(MatchesFlags, flags);
  233. }
  234. public static IEnumerable<FieldInfo> WithBindingFlags(this IEnumerable<FieldInfo> members, BindingFlags flags) {
  235. return members.WithBindingFlags(MatchesFlags, flags);
  236. }
  237. public static IEnumerable<PropertyInfo> WithBindingFlags(this IEnumerable<PropertyInfo> members, BindingFlags flags) {
  238. return members.WithBindingFlags(MatchesFlags, flags);
  239. }
  240. public static IEnumerable<EventInfo> WithBindingFlags(this IEnumerable<EventInfo> members, BindingFlags flags) {
  241. return members.WithBindingFlags(MatchesFlags, flags);
  242. }
  243. public static IEnumerable<TypeInfo> WithBindingFlags(this IEnumerable<TypeInfo> members, BindingFlags flags) {
  244. return members.WithBindingFlags(MatchesFlags, flags);
  245. }
  246. public static MemberInfo WithBindingFlags(this MemberInfo member, BindingFlags flags) {
  247. return member != null && MatchesFlags(member, flags) ? member : null;
  248. }
  249. public static MethodInfo WithBindingFlags(this MethodInfo member, BindingFlags flags) {
  250. return member != null && MatchesFlags(member, flags) ? member : null;
  251. }
  252. public static ConstructorInfo WithBindingFlags(this ConstructorInfo member, BindingFlags flags) {
  253. return member != null && MatchesFlags(member, flags) ? member : null;
  254. }
  255. public static FieldInfo WithBindingFlags(this FieldInfo member, BindingFlags flags) {
  256. return member != null && MatchesFlags(member, flags) ? member : null;
  257. }
  258. public static PropertyInfo WithBindingFlags(this PropertyInfo member, BindingFlags flags) {
  259. return member != null && MatchesFlags(member, flags) ? member : null;
  260. }
  261. public static EventInfo WithBindingFlags(this EventInfo member, BindingFlags flags) {
  262. return member != null && MatchesFlags(member, flags) ? member : null;
  263. }
  264. public static TypeInfo WithBindingFlags(this TypeInfo member, BindingFlags flags) {
  265. return member != null && MatchesFlags(member, flags) ? member : null;
  266. }
  267. #endregion
  268. #region Signatures
  269. public static IEnumerable<MethodInfo> WithSignature(this IEnumerable<MethodInfo> members, Type[] parameterTypes) {
  270. return members.Where(c => {
  271. var ps = c.GetParameters();
  272. if (ps.Length != parameterTypes.Length) {
  273. return false;
  274. }
  275. for (int i = 0; i < ps.Length; i++) {
  276. if (parameterTypes[i] != ps[i].ParameterType) {
  277. return false;
  278. }
  279. }
  280. return true;
  281. });
  282. }
  283. public static IEnumerable<ConstructorInfo> WithSignature(this IEnumerable<ConstructorInfo> members, Type[] parameterTypes) {
  284. return members.Where(c => {
  285. var ps = c.GetParameters();
  286. if (ps.Length != parameterTypes.Length) {
  287. return false;
  288. }
  289. for (int i = 0; i < ps.Length; i++) {
  290. if (parameterTypes[i] != ps[i].ParameterType) {
  291. return false;
  292. }
  293. }
  294. return true;
  295. });
  296. }
  297. #endregion
  298. #region Member Inheritance
  299. // CLI specification, partition I, 8.10.4: Hiding, overriding, and layout
  300. // ----------------------------------------------------------------------
  301. // While hiding applies to all members of a type, overriding deals with object layout and is applicable only to instance fields
  302. // and virtual methods. The CTS provides two forms of member overriding, new slot and expect existing slot. A member of a derived
  303. // type that is marked as a new slot will always get a new slot in the object’s layout, guaranteeing that the base field or method
  304. // is available in the object by using a qualified reference that combines the name of the base type with the name of the member
  305. // and its type or signature. A member of a derived type that is marked as expect existing slot will re-use (i.e., share or override)
  306. // a slot that corresponds to a member of the same kind (field or method), name, and type if one already exists from the base type;
  307. // if no such slot exists, a new slot is allocated and used.
  308. //
  309. // The general algorithm that is used for determining the names in a type and the layout of objects of the type is roughly as follows:
  310. // - Flatten the inherited names (using the hide by name or hide by name-and-signature rule) ignoring accessibility rules.
  311. // - For each new member that is marked “expect existing slot”, look to see if an exact match on kind (i.e., field or method),
  312. // name, and signature exists and use that slot if it is found, otherwise allocate a new slot.
  313. // - After doing this for all new members, add these new member-kind/name/signatures to the list of members of this type
  314. // - Finally, remove any inherited names that match the new members based on the hide by name or hide by name-and-signature rules.
  315. // NOTE: Following GetXxx only implement overriding, not hiding specified by hide-by-name or hide-by-name-and-signature flags.
  316. public static IEnumerable<MethodInfo> GetInheritedMethods(this Type type, string name = null, bool flattenHierarchy = false) {
  317. while (type.IsGenericParameter) {
  318. type = type.GetBaseType();
  319. }
  320. var baseDefinitions = new HashSet<MethodInfo>(ReferenceEqualityComparer<MethodInfo>.Instance);
  321. foreach (var ancestor in type.Ancestors()) {
  322. foreach (var declaredMethod in ancestor.GetDeclaredMethods(name)) {
  323. if (declaredMethod != null && IncludeMethod(declaredMethod, type, baseDefinitions, flattenHierarchy)) {
  324. yield return declaredMethod;
  325. }
  326. }
  327. }
  328. }
  329. private static bool IncludeMethod(MethodInfo member, Type reflectedType, HashSet<MethodInfo> baseDefinitions, bool flattenHierarchy) {
  330. if (member.IsVirtual) {
  331. if (baseDefinitions.Add(RuntimeReflectionExtensions.GetRuntimeBaseDefinition(member))) {
  332. return true;
  333. }
  334. } else if (member.DeclaringType == reflectedType) {
  335. return true;
  336. } else if (!member.IsPrivate && (!member.IsStatic || flattenHierarchy)) {
  337. return true;
  338. }
  339. return false;
  340. }
  341. public static IEnumerable<PropertyInfo> GetInheritedProperties(this Type type, string name = null, bool flattenHierarchy = false) {
  342. while (type.IsGenericParameter) {
  343. type = type.GetBaseType();
  344. }
  345. var baseDefinitions = new HashSet<MethodInfo>(ReferenceEqualityComparer<MethodInfo>.Instance);
  346. foreach (var ancestor in type.Ancestors()) {
  347. if (name != null) {
  348. var declaredProperty = ancestor.GetDeclaredProperty(name);
  349. if (declaredProperty != null && IncludeProperty(declaredProperty, type, baseDefinitions, flattenHierarchy)) {
  350. yield return declaredProperty;
  351. }
  352. } else {
  353. foreach (var declaredProperty in ancestor.GetDeclaredProperties()) {
  354. if (IncludeProperty(declaredProperty, type, baseDefinitions, flattenHierarchy)) {
  355. yield return declaredProperty;
  356. }
  357. }
  358. }
  359. }
  360. }
  361. // CLI spec 22.34 Properties
  362. // -------------------------
  363. // [Note: The CLS (see Partition I) refers to instance, virtual, and static properties.
  364. // The signature of a property (from the Type column) can be used to distinguish a static property,
  365. // since instance and virtual properties will have the “HASTHIS” bit set in the signature (§23.2.1)
  366. // while a static property will not. The distinction between an instance and a virtual property
  367. // depends on the signature of the getter and setter methods, which the CLS requires to be either
  368. // both virtual or both instance. end note]
  369. private static bool IncludeProperty(PropertyInfo member, Type reflectedType, HashSet<MethodInfo> baseDefinitions, bool flattenHierarchy) {
  370. var getter = member.GetGetMethod(nonPublic: true);
  371. var setter = member.GetSetMethod(nonPublic: true);
  372. MethodInfo virtualAccessor;
  373. if (getter != null && getter.IsVirtual) {
  374. virtualAccessor = getter;
  375. } else if (setter != null && setter.IsVirtual) {
  376. virtualAccessor = setter;
  377. } else {
  378. virtualAccessor = null;
  379. }
  380. if (virtualAccessor != null) {
  381. if (baseDefinitions.Add(RuntimeReflectionExtensions.GetRuntimeBaseDefinition(virtualAccessor))) {
  382. return true;
  383. }
  384. } else if (member.DeclaringType == reflectedType) {
  385. return true;
  386. } else if (!member.IsPrivate() && (!member.IsStatic() || flattenHierarchy)) {
  387. return true;
  388. }
  389. return false;
  390. }
  391. public static IEnumerable<EventInfo> GetInheritedEvents(this Type type, string name = null, bool flattenHierarchy = false) {
  392. while (type.IsGenericParameter) {
  393. type = type.GetBaseType();
  394. }
  395. var baseDefinitions = new HashSet<MethodInfo>(ReferenceEqualityComparer<MethodInfo>.Instance);
  396. foreach (var ancestor in type.Ancestors()) {
  397. if (name != null) {
  398. var declaredEvent = ancestor.GetDeclaredEvent(name);
  399. if (declaredEvent != null && IncludeEvent(declaredEvent, type, baseDefinitions, flattenHierarchy)) {
  400. yield return declaredEvent;
  401. }
  402. } else {
  403. foreach (var declaredEvent in ancestor.GetDeclaredEvents()) {
  404. if (IncludeEvent(declaredEvent, type, baseDefinitions, flattenHierarchy)) {
  405. yield return declaredEvent;
  406. }
  407. }
  408. }
  409. }
  410. }
  411. private static bool IncludeEvent(EventInfo member, Type reflectedType, HashSet<MethodInfo> baseDefinitions, bool flattenHierarchy) {
  412. var add = member.GetAddMethod(nonPublic: true);
  413. var remove = member.GetRemoveMethod(nonPublic: true);
  414. // TOOD: fire method?
  415. MethodInfo virtualAccessor;
  416. if (add != null && add.IsVirtual) {
  417. virtualAccessor = add;
  418. } else if (remove != null && remove.IsVirtual) {
  419. virtualAccessor = remove;
  420. } else {
  421. virtualAccessor = null;
  422. }
  423. if (virtualAccessor != null) {
  424. if (baseDefinitions.Add(RuntimeReflectionExtensions.GetRuntimeBaseDefinition(virtualAccessor))) {
  425. return true;
  426. }
  427. } else if (member.DeclaringType == reflectedType) {
  428. return true;
  429. } else if (!member.IsPrivate() && (!member.IsStatic() || flattenHierarchy)) {
  430. return true;
  431. }
  432. return false;
  433. }
  434. public static IEnumerable<FieldInfo> GetInheritedFields(this Type type, string name = null, bool flattenHierarchy = false) {
  435. while (type.IsGenericParameter) {
  436. type = type.GetBaseType();
  437. }
  438. foreach (var ancestor in type.Ancestors()) {
  439. if (name != null) {
  440. var declaredField = ancestor.GetDeclaredField(name);
  441. if (declaredField != null && IncludeField(declaredField, type, flattenHierarchy)) {
  442. yield return declaredField;
  443. }
  444. } else {
  445. foreach (var declaredField in ancestor.GetDeclaredFields()) {
  446. if (IncludeField(declaredField, type, flattenHierarchy)) {
  447. yield return declaredField;
  448. }
  449. }
  450. }
  451. }
  452. }
  453. private static bool IncludeField(FieldInfo member, Type reflectedType, bool flattenHierarchy) {
  454. if (member.DeclaringType == reflectedType) {
  455. return true;
  456. } else if (!member.IsPrivate && (!member.IsStatic || flattenHierarchy)) {
  457. return true;
  458. }
  459. return false;
  460. }
  461. public static IEnumerable<MemberInfo> GetInheritedMembers(this Type type, string name = null, bool flattenHierarchy = false) {
  462. var result =
  463. type.GetInheritedMethods(name, flattenHierarchy).Cast<MethodInfo, MemberInfo>().Concat(
  464. type.GetInheritedProperties(name, flattenHierarchy).Cast<PropertyInfo, MemberInfo>().Concat(
  465. type.GetInheritedEvents(name, flattenHierarchy).Cast<EventInfo, MemberInfo>().Concat(
  466. type.GetInheritedFields(name, flattenHierarchy).Cast<FieldInfo, MemberInfo>())));
  467. if (name == null) {
  468. return result.Concat<MemberInfo>(
  469. type.GetDeclaredConstructors().Cast<ConstructorInfo, MemberInfo>().Concat(
  470. type.GetDeclaredNestedTypes().Cast<TypeInfo, MemberInfo>()));
  471. }
  472. var nestedType = type.GetDeclaredNestedType(name);
  473. return (nestedType != null) ? result.Concat(new[] { nestedType }) : result;
  474. }
  475. #endregion
  476. #region Declared Members
  477. public static IEnumerable<ConstructorInfo> GetDeclaredConstructors(this Type type) {
  478. #if FEATURE_TYPE_INFO
  479. return type.GetTypeInfo().DeclaredConstructors;
  480. #else
  481. return type.GetConstructors(BindingFlags.DeclaredOnly | AllMembers);
  482. #endif
  483. }
  484. #if WIN8
  485. public static ConstructorInfo GetConstructor(this Type type, Type[] parameterTypes) {
  486. return type.GetDeclaredConstructors().Where(ci => !ci.IsStatic && ci.IsPublic).WithSignature(parameterTypes).SingleOrDefault();
  487. }
  488. #endif
  489. public static IEnumerable<MethodInfo> GetDeclaredMethods(this Type type, string name = null) {
  490. #if FEATURE_TYPE_INFO
  491. if (name == null) {
  492. return type.GetTypeInfo().DeclaredMethods;
  493. } else {
  494. return type.GetTypeInfo().GetDeclaredMethods(name);
  495. }
  496. #else
  497. if (name == null) {
  498. return type.GetMethods(BindingFlags.DeclaredOnly | AllMembers);
  499. } else {
  500. return type.GetMember(name, MemberTypes.Method, BindingFlags.DeclaredOnly | AllMembers).OfType<MethodInfo>();
  501. }
  502. #endif
  503. }
  504. public static IEnumerable<PropertyInfo> GetDeclaredProperties(this Type type) {
  505. #if FEATURE_TYPE_INFO
  506. return type.GetTypeInfo().DeclaredProperties;
  507. #else
  508. return type.GetProperties(BindingFlags.DeclaredOnly | AllMembers);
  509. #endif
  510. }
  511. public static PropertyInfo GetDeclaredProperty(this Type type, string name) {
  512. Debug.Assert(name != null);
  513. #if FEATURE_TYPE_INFO
  514. return type.GetTypeInfo().GetDeclaredProperty(name);
  515. #else
  516. return type.GetProperty(name, BindingFlags.DeclaredOnly | AllMembers);
  517. #endif
  518. }
  519. public static IEnumerable<EventInfo> GetDeclaredEvents(this Type type) {
  520. #if FEATURE_TYPE_INFO
  521. return type.GetTypeInfo().DeclaredEvents;
  522. #else
  523. return type.GetEvents(BindingFlags.DeclaredOnly | AllMembers);
  524. #endif
  525. }
  526. public static EventInfo GetDeclaredEvent(this Type type, string name) {
  527. Debug.Assert(name != null);
  528. #if FEATURE_TYPE_INFO
  529. return type.GetTypeInfo().GetDeclaredEvent(name);
  530. #else
  531. return type.GetEvent(name, BindingFlags.DeclaredOnly | AllMembers);
  532. #endif
  533. }
  534. public static IEnumerable<FieldInfo> GetDeclaredFields(this Type type) {
  535. #if FEATURE_TYPE_INFO
  536. return type.GetTypeInfo().DeclaredFields;
  537. #else
  538. return type.GetFields(BindingFlags.DeclaredOnly | AllMembers);
  539. #endif
  540. }
  541. public static FieldInfo GetDeclaredField(this Type type, string name) {
  542. Debug.Assert(name != null);
  543. #if FEATURE_TYPE_INFO
  544. return type.GetTypeInfo().GetDeclaredField(name);
  545. #else
  546. return type.GetField(name, BindingFlags.DeclaredOnly | AllMembers);
  547. #endif
  548. }
  549. public static IEnumerable<TypeInfo> GetDeclaredNestedTypes(this Type type) {
  550. #if FEATURE_TYPE_INFO
  551. return type.GetTypeInfo().DeclaredNestedTypes;
  552. #else
  553. return type.GetNestedTypes(BindingFlags.DeclaredOnly | AllMembers);
  554. #endif
  555. }
  556. public static TypeInfo GetDeclaredNestedType(this Type type, string name) {
  557. Debug.Assert(name != null);
  558. #if FEATURE_TYPE_INFO
  559. return type.GetTypeInfo().GetDeclaredNestedType(name);
  560. #else
  561. return type.GetNestedType(name, BindingFlags.DeclaredOnly | AllMembers);
  562. #endif
  563. }
  564. public static IEnumerable<MemberInfo> GetDeclaredMembers(this Type type, string name = null) {
  565. #if WIN8
  566. var info = type.GetTypeInfo();
  567. if (name == null) {
  568. return info.DeclaredMembers;
  569. } else {
  570. return GetDeclaredMembersWithName(info, name);
  571. }
  572. #else
  573. if (name == null) {
  574. return type.GetMembers(BindingFlags.DeclaredOnly | AllMembers);
  575. } else {
  576. return type.GetMember(name, BindingFlags.DeclaredOnly | AllMembers);
  577. }
  578. #endif
  579. }
  580. #if WIN8
  581. private static IEnumerable<MemberInfo> GetDeclaredMembersWithName(TypeInfo info, string name) {
  582. MemberInfo member;
  583. if ((member = info.GetDeclaredMethod(name)) != null) {
  584. yield return member;
  585. }
  586. if ((member = info.GetDeclaredField(name)) != null) {
  587. yield return member;
  588. }
  589. if ((member = info.GetDeclaredProperty(name)) != null) {
  590. yield return member;
  591. }
  592. if ((member = info.GetDeclaredEvent(name)) != null) {
  593. yield return member;
  594. }
  595. if ((member = info.GetDeclaredNestedType(name)) != null) {
  596. yield return member;
  597. }
  598. }
  599. #endif
  600. #endregion
  601. #region Win8
  602. #if WIN8
  603. public static TypeCode GetTypeCode(this Enum e) {
  604. return GetTypeCode(Enum.GetUnderlyingType(e.GetType()));
  605. }
  606. // TODO: reduce to numeric types?
  607. public static TypeCode GetTypeCode(this Type type) {
  608. if (type == typeof(int)) {
  609. return TypeCode.Int32;
  610. }
  611. if (type == typeof(sbyte)) {
  612. return TypeCode.SByte;
  613. }
  614. if (type == typeof(short)) {
  615. return TypeCode.Int16;
  616. }
  617. if (type == typeof(long)) {
  618. return TypeCode.Int64;
  619. }
  620. if (type == typeof(uint)) {
  621. return TypeCode.UInt32;
  622. }
  623. if (type == typeof(byte)) {
  624. return TypeCode.Byte;
  625. }
  626. if (type == typeof(ushort)) {
  627. return TypeCode.UInt16;
  628. }
  629. if (type == typeof(ulong)) {
  630. return TypeCode.UInt64;
  631. }
  632. if (type == typeof(bool)) {
  633. return TypeCode.Boolean;
  634. }
  635. if (type == typeof(char)) {
  636. return TypeCode.Char;
  637. }
  638. // TODO: do we need this?
  639. if (type == typeof(string)) {
  640. return TypeCode.String;
  641. }
  642. if (type == typeof(bool)) {
  643. return TypeCode.Boolean;
  644. }
  645. if (type == typeof(double)) {
  646. return TypeCode.Double;
  647. }
  648. if (type == typeof(float)) {
  649. return TypeCode.Single;
  650. }
  651. if (type == typeof(decimal)) {
  652. return TypeCode.Decimal;
  653. }
  654. if (type == typeof(DateTime)) {
  655. return TypeCode.DateTime;
  656. }
  657. return TypeCode.Object;
  658. }
  659. public static IEnumerable<Type> GetImplementedInterfaces(this Type type) {
  660. return type.GetTypeInfo().ImplementedInterfaces;
  661. }
  662. #if !NETSTANDARD
  663. public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo, bool nonPublic = false) {
  664. var accessor = propertyInfo.GetMethod;
  665. return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
  666. }
  667. public static MethodInfo GetSetMethod(this PropertyInfo propertyInfo, bool nonPublic = false) {
  668. var accessor = propertyInfo.SetMethod;
  669. return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
  670. }
  671. public static MethodInfo GetAddMethod(this EventInfo eventInfo, bool nonPublic = false) {
  672. var accessor = eventInfo.AddMethod;
  673. return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
  674. }
  675. public static MethodInfo GetRemoveMethod(this EventInfo eventInfo, bool nonPublic = false) {
  676. var accessor = eventInfo.RemoveMethod;
  677. return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
  678. }
  679. public static MethodInfo GetRaiseMethod(this EventInfo eventInfo, bool nonPublic = false) {
  680. var accessor = eventInfo.RaiseMethod;
  681. return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
  682. }
  683. public static MethodInfo GetMethod(this Type type, string name) {
  684. return type.GetTypeInfo().GetDeclaredMethod(name);
  685. }
  686. // TODO: FlattenHierarchy
  687. // TODO: inherited!
  688. public static MethodInfo GetMethod(this Type type, string name, Type[] parameterTypes) {
  689. return type.GetTypeInfo().GetDeclaredMethods(name).WithSignature(parameterTypes).Single();
  690. }
  691. public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags) {
  692. return type.GetMethods(name, bindingFlags).Single();
  693. }
  694. #endif
  695. private static IEnumerable<MethodInfo> GetMethods(this Type type, string name, BindingFlags bindingFlags) {
  696. return type.GetTypeInfo().GetDeclaredMethods(name).WithBindingFlags(bindingFlags);
  697. }
  698. public static Type CreateType(this TypeBuilder builder) {
  699. return builder.CreateTypeInfo().AsType();
  700. }
  701. #if !NETSTANDARD
  702. public static object GetRawConstantValue(this FieldInfo field) {
  703. return ((dynamic)field).GetRawConstantValue();
  704. }
  705. public static int GetMetadataToken(this MemberInfo member) {
  706. return ((dynamic)member).MetadataToken;
  707. }
  708. #endif
  709. public static Module GetModule(this MemberInfo member) {
  710. return member.Module;
  711. }
  712. #if !NETSTANDARD
  713. public static Type[] GetGenericArguments(this Type type) {
  714. return type.GetTypeInfo().GenericTypeArguments;
  715. }
  716. public static bool IsAssignableFrom(this Type type, Type other) {
  717. return type.GetTypeInfo().IsAssignableFrom(other.GetTypeInfo());
  718. }
  719. #endif
  720. public static Type[] GetGenericParameterConstraints(this Type type) {
  721. return type.GetTypeInfo().GetGenericParameterConstraints();
  722. }
  723. public static bool IsSubclassOf(this Type type, Type other) {
  724. return type.GetTypeInfo().IsSubclassOf(other);
  725. }
  726. #if !NETSTANDARD
  727. public static IEnumerable<Type> GetInterfaces(this Type type) {
  728. return type.GetTypeInfo().ImplementedInterfaces;
  729. }
  730. #endif
  731. public static Type[] GetRequiredCustomModifiers(this ParameterInfo parameter) {
  732. return EmptyTypes;
  733. }
  734. public static Type[] GetOptionalCustomModifiers(this ParameterInfo parameter) {
  735. return EmptyTypes;
  736. }
  737. public static IEnumerable<Module> GetModules(this Assembly assembly) {
  738. return assembly.Modules;
  739. }
  740. private static string GetDefaultMemberName(this Type type) {
  741. foreach (var ancestor in type.Ancestors()) {
  742. var attr = ancestor.GetTypeInfo().GetCustomAttributes<DefaultMemberAttribute>().SingleOrDefault();
  743. if (attr != null) {
  744. return attr.MemberName;
  745. }
  746. }
  747. return null;
  748. }
  749. #if !NETSTANDARD
  750. public static IEnumerable<MemberInfo> GetDefaultMembers(this Type type) {
  751. string defaultMemberName = type.GetDefaultMemberName();
  752. if (defaultMemberName != null) {
  753. return type.GetInheritedMembers(defaultMemberName).WithBindingFlags(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
  754. }
  755. return Enumerable.Empty<MemberInfo>();
  756. }
  757. #endif
  758. #else
  759. public static IEnumerable<Module> GetModules(this Assembly assembly) {
  760. return assembly.GetModules();
  761. }
  762. public static IEnumerable<Type> GetImplementedInterfaces(this Type type) {
  763. return type.GetInterfaces();
  764. }
  765. public static TypeCode GetTypeCode(this Type type) {
  766. return Type.GetTypeCode(type);
  767. }
  768. public static int GetMetadataToken(this MemberInfo member) {
  769. return member.MetadataToken;
  770. }
  771. public static Module GetModule(this MemberInfo member) {
  772. return member.Module;
  773. }
  774. public static bool IsDefined(this Assembly assembly, Type attributeType) {
  775. return assembly.IsDefined(attributeType, false);
  776. }
  777. #if !CLR45
  778. public static T GetCustomAttribute<T>(this Assembly assembly, bool inherit = false) where T : Attribute {
  779. return (T)Attribute.GetCustomAttribute(assembly, typeof(T), inherit);
  780. }
  781. public static T GetCustomAttribute<T>(this MemberInfo member, bool inherit = false) where T : Attribute {
  782. return (T)Attribute.GetCustomAttribute(member, typeof(T), inherit);
  783. }
  784. public static IEnumerable<T> GetCustomAttributes<T>(this Assembly assembly, bool inherit = false) where T : Attribute {
  785. return Attribute.GetCustomAttributes(assembly, typeof(T), inherit).Cast<T>();
  786. }
  787. public static IEnumerable<T> GetCustomAttributes<T>(this MemberInfo member, bool inherit = false) where T : Attribute {
  788. return Attribute.GetCustomAttributes(member, typeof(T), inherit).Cast<T>();
  789. }
  790. #endif
  791. #endif
  792. public static MethodInfo GetMethod(this Delegate d) {
  793. return d.GetMethodInfo();
  794. }
  795. public static bool ContainsGenericParameters(this Type type) {
  796. return type.GetTypeInfo().ContainsGenericParameters;
  797. }
  798. public static bool IsInterface(this Type type) {
  799. return type.GetTypeInfo().IsInterface;
  800. }
  801. public static bool IsClass(this Type type) {
  802. return type.GetTypeInfo().IsClass;
  803. }
  804. public static bool IsGenericType(this Type type) {
  805. return type.GetTypeInfo().IsGenericType;
  806. }
  807. public static bool IsGenericTypeDefinition(this Type type) {
  808. return type.GetTypeInfo().IsGenericTypeDefinition;
  809. }
  810. public static bool IsSealed(this Type type) {
  811. return type.GetTypeInfo().IsSealed;
  812. }
  813. public static bool IsAbstract(this Type type) {
  814. return type.GetTypeInfo().IsAbstract;
  815. }
  816. public static bool IsPublic(this Type type) {
  817. return type.GetTypeInfo().IsPublic;
  818. }
  819. public static bool IsVisible(this Type type) {
  820. return type.GetTypeInfo().IsVisible;
  821. }
  822. public static Type GetBaseType(this Type type) {
  823. return type.GetTypeInfo().BaseType;
  824. }
  825. public static bool IsValueType(this Type type) {
  826. return type.GetTypeInfo().IsValueType;
  827. }
  828. public static bool IsEnum(this Type type) {
  829. return type.GetTypeInfo().IsEnum;
  830. }
  831. public static bool IsPrimitive(this Type type) {
  832. return type.GetTypeInfo().IsPrimitive;
  833. }
  834. public static GenericParameterAttributes GetGenericParameterAttributes(this Type type) {
  835. return type.GetTypeInfo().GenericParameterAttributes;
  836. }
  837. public static Type[] EmptyTypes = new Type[0];
  838. #endregion
  839. #if FEATURE_REFEMIT
  840. #if FEATURE_ASSEMBLYBUILDER_DEFINEDYNAMICASSEMBLY
  841. public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) {
  842. return AssemblyBuilder.DefineDynamicAssembly(name, access);
  843. }
  844. #else
  845. public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) {
  846. return AppDomain.CurrentDomain.DefineDynamicAssembly(name, access);
  847. }
  848. #endif
  849. #if !FEATURE_PDBEMIT
  850. public static ModuleBuilder DefineDynamicModule(this AssemblyBuilder assembly, string name, bool emitDebugInfo) {
  851. // ignore the flag
  852. return assembly.DefineDynamicModule(name);
  853. }
  854. #endif
  855. #endif
  856. #region Signature and Type Formatting
  857. // Generic type names have the arity (number of generic type paramters) appended at the end.
  858. // For eg. the mangled name of System.List<T> is "List`1". This mangling is done to enable multiple
  859. // generic types to exist as long as they have different arities.
  860. public const char GenericArityDelimiter = '`';
  861. #if !WIN8
  862. public static StringBuilder FormatSignature(StringBuilder result, MethodBase method) {
  863. return FormatSignature(result, method, (t) => t.FullName);
  864. }
  865. public static StringBuilder FormatSignature(StringBuilder result, MethodBase method, Func<Type, string> nameDispenser) {
  866. ContractUtils.RequiresNotNull(result, "result");
  867. ContractUtils.RequiresNotNull(method, "method");
  868. ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
  869. MethodInfo methodInfo = method as MethodInfo;
  870. if (methodInfo != null) {
  871. FormatTypeName(result, methodInfo.ReturnType, nameDispenser);
  872. result.Append(' ');
  873. }
  874. #if FEATURE_REFEMIT && !NETSTANDARD
  875. MethodBuilder builder = method as MethodBuilder;
  876. if (builder != null) {
  877. result.Append(builder.Signature);
  878. return result;
  879. }
  880. ConstructorBuilder cb = method as ConstructorBuilder;
  881. if (cb != null) {
  882. result.Append(cb.Signature);
  883. return result;
  884. }
  885. #endif
  886. FormatTypeName(result, method.DeclaringType, nameDispenser);
  887. result.Append("::");
  888. result.Append(method.Name);
  889. if (!method.IsConstructor) {
  890. FormatTypeArgs(result, method.GetGenericArguments(), nameDispenser);
  891. }
  892. result.Append("(");
  893. if (!method.ContainsGenericParameters) {
  894. ParameterInfo[] ps = method.GetParameters();
  895. for (int i = 0; i < ps.Length; i++) {
  896. if (i > 0) result.Append(", ");
  897. FormatTypeName(result, ps[i].ParameterType, nameDispenser);
  898. if (!System.String.IsNullOrEmpty(ps[i].Name)) {
  899. result.Append(" ");
  900. result.Append(ps[i].Name);
  901. }
  902. }
  903. } else {
  904. result.Append("?");
  905. }
  906. result.Append(")");
  907. return result;
  908. }
  909. #endif
  910. public static StringBuilder FormatTypeName(StringBuilder result, Type type) {
  911. return FormatTypeName(result, type, (t) => t.FullName);
  912. }
  913. public static StringBuilder FormatTypeName(StringBuilder result, Type type, Func<Type, string> nameDispenser) {
  914. ContractUtils.RequiresNotNull(result, "result");
  915. ContractUtils.RequiresNotNull(type, "type");
  916. ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
  917. if (type.IsGenericType()) {
  918. Type genType = type.GetGenericTypeDefinition();
  919. string genericName = nameDispenser(genType).Replace('+', '.');
  920. int tickIndex = genericName.IndexOf('`');
  921. result.Append(tickIndex != -1 ? genericName.Substring(0, tickIndex) : genericName);
  922. Type[] typeArgs = type.GetGenericArguments();
  923. if (type.IsGenericTypeDefinition()) {
  924. result.Append('<');
  925. result.Append(',', typeArgs.Length - 1);
  926. result.Append('>');
  927. } else {
  928. FormatTypeArgs(result, typeArgs, nameDispenser);
  929. }
  930. } else if (type.IsGenericParameter) {
  931. result.Append(type.Name);
  932. } else {
  933. // cut namespace off:
  934. result.Append(nameDispenser(type).Replace('+', '.'));
  935. }
  936. return result;
  937. }
  938. public static StringBuilder FormatTypeArgs(StringBuilder result, Type[] types) {
  939. return FormatTypeArgs(result, types, (t) => t.FullName);
  940. }
  941. public static StringBuilder FormatTypeArgs(StringBuilder result, Type[] types, Func<Type, string> nameDispenser) {
  942. ContractUtils.RequiresNotNull(result, "result");
  943. ContractUtils.RequiresNotNullItems(types, "types");
  944. ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
  945. if (types.Length > 0) {
  946. result.Append("<");
  947. for (int i = 0; i < types.Length; i++) {
  948. if (i > 0) result.Append(", ");
  949. FormatTypeName(result, types[i], nameDispenser);
  950. }
  951. result.Append(">");
  952. }
  953. return result;
  954. }
  955. internal static string ToValidTypeName(string str) {
  956. if (String.IsNullOrEmpty(str)) {
  957. return "_";
  958. }
  959. StringBuilder sb = new StringBuilder(str);
  960. for (int i = 0; i < str.Length; i++) {
  961. if (str[i] == '\0' || str[i] == '.' || str[i] == '*' || str[i] == '+' || str[i] == '[' || str[i] == ']' || str[i] == '\\') {
  962. sb[i] = '_';
  963. }
  964. }
  965. return sb.ToString();
  966. }
  967. public static string GetNormalizedTypeName(Type type) {
  968. string name = type.Name;
  969. if (type.IsGenericType()) {
  970. return GetNormalizedTypeName(name);
  971. }
  972. return name;
  973. }
  974. public static string GetNormalizedTypeName(string typeName) {
  975. Debug.Assert(typeName.IndexOf('.') == -1); // This is the simple name, not the full name
  976. int backtick = typeName.IndexOf(ReflectionUtils.GenericArityDelimiter);
  977. if (backtick != -1) return typeName.Substring(0, backtick);
  978. return typeName;
  979. }
  980. #endregion
  981. #region Delegates and Dynamic Methods
  982. #if WP75
  983. /// <summary>
  984. /// Creates an open delegate for the given (dynamic)method.
  985. /// </summary>
  986. public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType) {
  987. return CreateDelegate(methodInfo, delegateType, null);
  988. }
  989. /// <summary>
  990. /// Creates a closed delegate for the given (dynamic)method.
  991. /// </summary>
  992. public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
  993. return Delegate.CreateDelegate(delegateType, target, methodInfo);
  994. }
  995. #elif !WIN8 && !NETSTANDARD
  996. /// <summary>
  997. /// Creates an open delegate for the given (dynamic)method.
  998. /// </summary>
  999. public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType) {
  1000. return CreateDelegate(methodInfo, delegateType, null);
  1001. }
  1002. /// <summary>
  1003. /// Creates a closed delegate for the given (dynamic)method.
  1004. /// </summary>
  1005. public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
  1006. DynamicMethod dm = methodInfo as DynamicMethod;
  1007. if (dm != null) {
  1008. return dm.CreateDelegate(delegateType, target);
  1009. } else {
  1010. return Delegate.CreateDelegate(delegateType, target, methodInfo);
  1011. }
  1012. }
  1013. #endif
  1014. public static bool IsDynamicMethod(MethodBase method) {
  1015. return !PlatformAdaptationLayer.IsCompactFramework && IsDynamicMethodInternal(method);
  1016. }
  1017. [MethodImpl(MethodImplOptions.NoInlining)]
  1018. private static bool IsDynamicMethodInternal(MethodBase method) {
  1019. return method is DynamicMethod;
  1020. }
  1021. public static void GetDelegateSignature(Type delegateType, out ParameterInfo[] parameterInfos, out ParameterInfo returnInfo) {
  1022. ContractUtils.RequiresNotNull(delegateType, "delegateType");
  1023. MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
  1024. ContractUtils.Requires(invokeMethod != null, "delegateType", Strings.InvalidDelegate);
  1025. parameterInfos = invokeMethod.GetParameters();
  1026. returnInfo = invokeMethod.ReturnParameter;
  1027. }
  1028. /// <summary>
  1029. /// Gets a Func of CallSite, object * paramCnt, object delegate type
  1030. /// that's suitable for use in a non-strongly typed call site.
  1031. /// </summary>
  1032. public static Type GetObjectCallSiteDelegateType(int paramCnt) {
  1033. switch (paramCnt) {
  1034. case 0: return typeof(Func<CallSite, object, object>);
  1035. case 1: return typeof(Func<CallSite, object, object, object>);
  1036. case 2: return typeof(Func<CallSite, object, object, object, object>);
  1037. case 3: return typeof(Func<CallSite, object, object, object, object, object>);
  1038. case 4: return typeof(Func<CallSite, object, object, object, object, object, object>);
  1039. case 5: return typeof(Func<CallSite, object, object, object, object, object, object, object>);
  1040. case 6: return typeof(Func<CallSite, object, object, object, object, object, object, object, object>);
  1041. case 7: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object>);
  1042. case 8: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object>);
  1043. case 9: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object>);
  1044. case 10: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object>);
  1045. case 11: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object>);
  1046. case 12: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
  1047. case 13: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
  1048. case 14: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
  1049. default:
  1050. #if FEATURE_REFEMIT
  1051. Type[] paramTypes = new Type[paramCnt + 2];
  1052. paramTypes[0] = typeof(CallSite);
  1053. paramTypes[1] = typeof(object);
  1054. for (int i = 0; i < paramCnt; i++) {
  1055. paramTypes[i + 2] = typeof(object);
  1056. }
  1057. return Snippets.Shared.DefineDelegate("InvokeDelegate" + paramCnt, typeof(object), paramTypes);
  1058. #else
  1059. throw new NotSupportedException("Signature not supported on this platform.");
  1060. #endif
  1061. }
  1062. }
  1063. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework")]
  1064. internal static DynamicMethod RawCreateDynamicMethod(string name, Type returnType, Type[] parameterTypes) {
  1065. #if SILVERLIGHT // Module-hosted DynamicMethod is not available in SILVERLIGHT
  1066. return new DynamicMethod(name, returnType, parameterTypes);
  1067. #else
  1068. //
  1069. // WARNING: we set restrictedSkipVisibility == true (last parameter)
  1070. // setting this bit will allow accessing nonpublic members
  1071. // for more information see http://msdn.microsoft.com/en-us/library/bb348332.aspx
  1072. //
  1073. return new DynamicMethod(name, returnType, parameterTypes, true);
  1074. #endif
  1075. }
  1076. #endregion
  1077. #region Methods and Parameters
  1078. public static MethodInfo[] GetMethodInfos(Delegate[] delegates) {
  1079. MethodInfo[] result = new MethodInfo[delegates.Length];
  1080. for (int i = 0; i < delegates.Length; i++) result[i] = delegates[i].GetMethod();
  1081. return result;
  1082. }
  1083. public static MethodBase[] GetMethodInfos(MemberInfo[] members) {
  1084. return ArrayUtils.ConvertAll<MemberInfo, MethodBase>(
  1085. members,
  1086. delegate(MemberInfo inp) { return (MethodBase)inp; });
  1087. }
  1088. public static Type[] GetParameterTypes(ParameterInfo[] parameterInfos) {
  1089. return GetParameterTypes((IList<ParameterInfo>)parameterInfos);
  1090. }
  1091. public static Type[] GetParameterTypes(IList<ParameterInfo> parameterInfos) {
  1092. Type[] result = new Type[parameterInfos.Count];
  1093. for (int i = 0; i < result.Length; i++) {
  1094. result[i] = parameterInfos[i].ParameterType;
  1095. }
  1096. return result;
  1097. }
  1098. public static Type GetReturnType(this MethodBase mi) {
  1099. return (mi.IsConstructor) ? mi.DeclaringType : ((MethodInfo)mi).ReturnType;
  1100. }
  1101. public static bool SignatureEquals(MethodInfo method, params Type[] requiredSignature) {
  1102. ContractUtils.RequiresNotNull(method, "method");
  1103. Type[] actualTypes = ReflectionUtils.GetParameterTypes(method.GetParameters());
  1104. Debug.Assert(actualTypes.Length == requiredSignature.Length - 1);
  1105. int i = 0;
  1106. while (i < actualTypes.Length) {
  1107. if (actualTypes[i] != requiredSignature[i]) return false;
  1108. i++;
  1109. }
  1110. return method.ReturnType == requiredSignature[i];
  1111. }
  1112. #if CLR2 && !SILVERLIGHT
  1113. private static Type _ExtensionAttributeType;
  1114. #endif
  1115. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
  1116. public static bool IsExtension(this MemberInfo member) {
  1117. var dlrExtension = typeof(ExtensionAttribute);
  1118. if (member.IsDefined(dlrExtension, false)) {
  1119. return true;
  1120. }
  1121. #if CLR2 && !SILVERLIGHT
  1122. if (_ExtensionAttributeType == null) {
  1123. try {
  1124. _ExtensionAttributeType = Assembly.Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
  1125. .GetType("System.Runtime.CompilerServices.ExtensionAttribute");
  1126. } catch {
  1127. _ExtensionAttributeType = dlrExtension;
  1128. }
  1129. }
  1130. if (_ExtensionAttributeType != dlrExtension) {
  1131. return member.IsDefined(_ExtensionAttributeType, false);
  1132. }
  1133. #endif
  1134. return false;
  1135. }
  1136. public static bool IsOutParameter(this ParameterInfo pi) {
  1137. // not using IsIn/IsOut properties as they are not available in Silverlight:
  1138. return pi.ParameterType.IsByRef && (pi.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out;
  1139. }
  1140. /// <summary>
  1141. /// Returns <c>true</c> if the specified parameter is mandatory, i.e. is not optional and doesn't have a default value.
  1142. /// </summary>
  1143. public static bool IsMandatory(this ParameterInfo pi) {
  1144. return (pi.Attributes & ParameterAttributes.Optional) == 0 && !pi.HasDefaultValue();
  1145. }
  1146. public static bool HasDefaultValue(this ParameterInfo pi) {
  1147. #if !FEATURE_DEFAULT_PARAMETER_VALUE
  1148. return pi.IsDefined(typeof(DefaultParameterValueAttribute), false);
  1149. #else
  1150. return (pi.Attributes & ParameterAttributes.HasDefault) != 0;
  1151. #endif
  1152. }
  1153. public static bool ProhibitsNull(this ParameterInfo parameter) {
  1154. return parameter.IsDefined(typeof(NotNullAttribute), false);
  1155. }
  1156. public static bool ProhibitsNullItems(this ParameterInfo parameter) {
  1157. return parameter.IsDefined(typeof(NotNullItemsAttribute), false);
  1158. }
  1159. public static bool IsParamArray(this ParameterInfo parameter) {
  1160. return parameter.IsDefined(typeof(ParamArrayAttribute), false);
  1161. }
  1162. public static bool IsParamDictionary(this ParameterInfo parameter) {
  1163. return parameter.IsDefined(typeof(ParamDictionaryAttribute), false);
  1164. }
  1165. public static bool IsParamsMethod(MethodBase method) {
  1166. return IsParamsMethod(method.GetParameters());
  1167. }
  1168. public static bool IsParamsMethod(ParameterInfo[] pis) {
  1169. foreach (ParameterInfo pi in pis) {
  1170. if (pi.IsParamArray() || pi.IsParamDictionary()) return true;
  1171. }
  1172. return false;
  1173. }
  1174. public static object GetDefaultValue(this ParameterInfo info) {
  1175. #if !FEATURE_DEFAULT_PARAMETER_VALUE
  1176. if (info.IsOptional) {
  1177. return info.ParameterType == typeof(object) ? Missing.Value : ScriptingRuntimeHelpers.GetPrimitiveDefaultValue(info.ParameterType);
  1178. }
  1179. var defaultValueAttribute = info.GetCustomAttributes(typeof(DefaultParameterValueAttribute), false);
  1180. if (defaultValueAttribute.Length > 0) {
  1181. return ((DefaultParameterValueAttribute)defaultValueAttribute[0]).Value;
  1182. }
  1183. return null;
  1184. #else
  1185. return info.DefaultValue;
  1186. #endif
  1187. }
  1188. #endregion
  1189. #region Types
  1190. /// <summary>
  1191. /// Yields all ancestors of the given type including the type itself.
  1192. /// Does not include implemented interfaces.
  1193. /// </summary>
  1194. public static IEnumerable<Type> Ancestors(this Type type) {
  1195. do {
  1196. yield return type;
  1197. type = type.GetTypeInfo().BaseType;
  1198. } while (type != null);
  1199. }
  1200. /// <summary>
  1201. /// Like Type.GetInterfaces, but only returns the interfaces implemented by this type
  1202. /// and not its parents.
  1203. /// </summary>
  1204. public static List<Type> GetDeclaredInterfaces(Type type) {
  1205. IEnumerable<Type> baseInterfaces = (type.GetBaseType() != null) ? type.GetBaseType().GetInterfaces() : EmptyTypes;
  1206. List<Type> interfaces = new List<Type>();
  1207. foreach (Type iface in type.GetInterfaces()) {
  1208. if (!baseInterfaces.Contains(iface)) {
  1209. interfaces.Add(iface);
  1210. }
  1211. }
  1212. return interfaces;
  1213. }
  1214. internal static IEnumerable<TypeInfo> GetAllTypesFromAssembly(Assembly asm) {
  1215. // TODO: WP7, SL5
  1216. #if SILVERLIGHT // ReflectionTypeLoadException
  1217. try {
  1218. return asm.GetTypes();
  1219. } catch (Exception) {
  1220. return ReflectionUtils.EmptyTypes;
  1221. }
  1222. #elif WIN8
  1223. return asm.DefinedTypes;
  1224. #else
  1225. foreach (Module module in asm.GetModules()) {
  1226. Type[] moduleTypes;
  1227. try {
  1228. moduleTypes = module.GetTypes();
  1229. } catch (ReflectionTypeLoadException e) {
  1230. moduleTypes = e.Types;
  1231. }
  1232. foreach (var type in moduleTypes) {
  1233. if (type != null) {
  1234. yield return type.GetTypeInfo();
  1235. }
  1236. }
  1237. }
  1238. #endif
  1239. }
  1240. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
  1241. internal static IEnumerable<TypeInfo> GetAllTypesFromAssembly(Assembly assembly, bool includePrivateTypes) {
  1242. ContractUtils.RequiresNotNull(assembly, "assembly");
  1243. if (includePrivateTypes) {
  1244. return GetAllTypesFromAssembly(assembly);
  1245. }
  1246. try {
  1247. #if WIN8
  1248. return assembly.ExportedTypes.Select(t => t.GetTypeInfo());
  1249. #else
  1250. return assembly.GetExportedTypes().Select(t => t.GetTypeInfo());
  1251. #endif
  1252. } catch (NotSupportedException) {
  1253. // GetExportedTypes does not work with dynamic assemblies
  1254. } catch (Exception) {
  1255. // Some type loads may cause exceptions. Unfortunately, there is no way to ask GetExportedTypes
  1256. // for just the list of types that we successfully loaded.
  1257. }
  1258. return GetAllTypesFromAssembly(assembly).Where(type => type.IsPublic);
  1259. }
  1260. #endregion
  1261. #region Type Builder
  1262. #if FEATURE_REFEMIT
  1263. private const MethodAttributes MethodAttributesReservedMask = (MethodAttributes)0xD000; // MethodAttributes.ReservedMask
  1264. private const MethodAttributes MethodAttributesToEraseInOveride = MethodAttributes.Abstract | MethodAttributesReservedMask;
  1265. public static MethodBuilder DefineMethodOverride(TypeBuilder tb, MethodAttributes extra, MethodInfo decl) {
  1266. MethodAttributes finalAttrs = (decl.Attributes & ~MethodAttributesToEraseInOveride) | extra;
  1267. if (!decl.DeclaringType.GetTypeInfo().IsInterface) {
  1268. finalAttrs &= ~MethodAttributes.NewSlot;
  1269. }
  1270. if ((extra & MethodAttributes.MemberAccessMask) != 0) {
  1271. // remove existing member access, add new member access
  1272. finalAttrs &= ~MethodAttributes.MemberAccessMask;
  1273. finalAttrs |= extra;
  1274. }
  1275. MethodBuilder impl = tb.DefineMethod(decl.Name, finalAttrs, decl.CallingConvention);
  1276. CopyMethodSignature(decl, impl, false);
  1277. return impl;
  1278. }
  1279. public static void CopyMethodSignature(MethodInfo from, MethodBuilder to, bool substituteDeclaringType) {
  1280. ParameterInfo[] paramInfos = from.GetParameters();
  1281. Type[] parameterTypes = new Type[paramInfos.Length];
  1282. Type[][] parameterRequiredModifiers = null, parameterOptionalModifiers = null;
  1283. Type[] returnRequiredModifiers = null, returnOptionalModifiers = null;
  1284. #if FEATURE_CUSTOM_MODIFIERS
  1285. returnRequiredModifiers = from.ReturnParameter.GetRequiredCustomModifiers();
  1286. returnOptionalModifiers = from.ReturnParameter.GetOptionalCustomModifiers();
  1287. #endif
  1288. for (int i = 0; i < paramInfos.Length; i++) {
  1289. if (substituteDeclaringType && paramInfos[i].ParameterType == from.DeclaringType) {
  1290. parameterTypes[i] = to.DeclaringType;
  1291. } else {
  1292. parameterTypes[i] = paramInfos[i].ParameterType;
  1293. }
  1294. #if FEATURE_CUSTOM_MODIFIERS
  1295. var mods = paramInfos[i].GetRequiredCustomModifiers();
  1296. if (mods.Length > 0) {
  1297. if (parameterRequiredModifiers == null) {
  1298. parameterRequiredModifiers = new Type[paramInfos.Length][];
  1299. }
  1300. parameterRequiredModifiers[i] = mods;
  1301. }
  1302. mods = paramInfos[i].GetOptionalCustomModifiers();
  1303. if (mods.Length > 0) {
  1304. if (parameterOptionalModifiers == null) {
  1305. parameterOptionalModifiers = new Type[paramInfos.Length][];
  1306. }
  1307. parameterOptionalModifiers[i] = mods;
  1308. }
  1309. #endif
  1310. }
  1311. to.SetSignature(
  1312. from.ReturnType, returnRequiredModifiers, returnOptionalModifiers,
  1313. parameterTypes, parameterRequiredModifiers, parameterOptionalModifiers
  1314. );
  1315. CopyGenericMethodAttributes(from, to);
  1316. for (int i = 0; i < paramInfos.Length; i++) {
  1317. to.DefineParameter(i + 1, paramInfos[i].Attributes, paramInfos[i].Name);
  1318. }
  1319. }
  1320. private static void CopyGenericMethodAttributes(MethodInfo from, MethodBuilder to) {
  1321. if (from.IsGenericMethodDefinition) {
  1322. Type[] args = from.GetGenericArguments();
  1323. string[] names = new string[args.Length];
  1324. for (int i = 0; i < args.Length; i++) {
  1325. names[i] = args[i].Name;
  1326. }
  1327. var builders = to.DefineGenericParameters(names);
  1328. for (int i = 0; i < args.Length; i++) {
  1329. // Copy template parameter attributes
  1330. builders[i].SetGenericParameterAttributes(args[i].GetGenericParameterAttributes());
  1331. // Copy template parameter constraints
  1332. Type[] constraints = args[i].GetGenericParameterConstraints();
  1333. List<Type> interfaces = new List<Type>(constraints.Length);
  1334. foreach (Type constraint in constraints) {
  1335. if (constraint.IsInterface()) {
  1336. interfaces.Add(constraint);
  1337. } else {
  1338. builders[i].SetBaseTypeConstraint(constraint);
  1339. }
  1340. }
  1341. if (interfaces.Count > 0) {
  1342. builders[i].SetInterfaceConstraints(interfaces.ToArray());
  1343. }
  1344. }
  1345. }
  1346. }
  1347. #endif
  1348. #endregion
  1349. #region Extension Methods
  1350. public static IEnumerable<MethodInfo> GetVisibleExtensionMethods(Assembly assembly) {
  1351. #if FEATURE_METADATA_READER
  1352. if (!assembly.IsDynamic && AppDomain.CurrentDomain.IsFullyTrusted) {
  1353. try {
  1354. return GetVisibleExtensionMethodsFast(assembly);
  1355. } catch (SecurityException) {
  1356. // full-demand can still fail if there is a partial trust domain on the stack
  1357. }
  1358. }
  1359. #endif
  1360. return GetVisibleExtensionMethodsSlow(assembly);
  1361. }
  1362. #if FEATURE_METADATA_READER
  1363. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods")]
  1364. [MethodImpl(MethodImplOptions.NoInlining)]
  1365. private static IEnumerable<MethodInfo> GetVisibleExtensionMethodsFast(Assembly assembly) {
  1366. // Security: link demand
  1367. return MetadataServices.GetVisibleExtensionMethodInfos(assembly);
  1368. }
  1369. #endif
  1370. // TODO: make internal
  1371. // TODO: handle type load exceptions
  1372. public static IEnumerable<MethodInfo> GetVisibleExtensionMethodsSlow(Assembly assembly) {
  1373. var ea = typeof(ExtensionAttribute);
  1374. if (assembly.IsDefined(ea)) {
  1375. foreach (TypeInfo type in ReflectionUtils.GetAllTypesFromAssembly(assembly)) {
  1376. if ((type.IsPublic || type.IsNestedPublic) &&
  1377. type.IsAbstract &&
  1378. type.IsSealed &&
  1379. type.IsDefined(ea, false)) {
  1380. foreach (MethodInfo method in type.AsType().GetDeclaredMethods()) {
  1381. if (method.IsPublic && method.IsStatic && method.IsDefined(ea, false)) {
  1382. yield return method;
  1383. }
  1384. }
  1385. }
  1386. }
  1387. }
  1388. }
  1389. // Value is null if there are no extension methods in the assembly.
  1390. private static Dictionary<Assembly, Dictionary<string, List<ExtensionMethodInfo>>> _extensionMethodsCache;
  1391. /// <summary>
  1392. /// Enumerates extension methods in given assembly. Groups the methods by declaring namespace.
  1393. /// Uses a global cache if <paramref name="useCache"/> is true.
  1394. /// </summary>
  1395. public static IEnumerable<KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>> GetVisibleExtensionMethodGroups(Assembly/*!*/ assembly, bool useCache) {
  1396. #if !CLR2 && FEATURE_REFEMIT
  1397. useCache &= !assembly.IsDynamic;
  1398. #endif
  1399. if (useCache) {
  1400. if (_extensionMethodsCache == null) {
  1401. _extensionMethodsCache = new Dictionary<Assembly, Dictionary<string, List<ExtensionMethodInfo>>>();
  1402. }
  1403. lock (_extensionMethodsCache) {
  1404. Dictionary<string, List<ExtensionMethodInfo>> existing;
  1405. if (_extensionMethodsCache.TryGetValue(assembly, out existing)) {
  1406. return EnumerateExtensionMethods(existing);
  1407. }
  1408. }
  1409. }
  1410. Dictionary<string, List<ExtensionMethodInfo>> result = null;
  1411. foreach (MethodInfo method in ReflectionUtils.GetVisibleExtensionMethodsSlow(assembly)) {
  1412. if (method.DeclaringType == null || method.DeclaringType.IsGenericTypeDefinition()) {
  1413. continue;
  1414. }
  1415. var parameters = method.GetParameters();
  1416. if (parameters.Length == 0) {
  1417. continue;
  1418. }
  1419. Type type = parameters[0].ParameterType;
  1420. if (type.IsByRef || type.IsPointer) {
  1421. continue;
  1422. }
  1423. string ns = method.DeclaringType.Namespace ?? String.Empty;
  1424. List<ExtensionMethodInfo> extensions = null;
  1425. if (result == null) {
  1426. result = new Dictionary<string, List<ExtensionMethodInfo>>();
  1427. }
  1428. if (!result.TryGetValue(ns, out extensions)) {
  1429. result.Add(ns, extensions = new List<ExtensionMethodInfo>());
  1430. }
  1431. extensions.Add(new ExtensionMethodInfo(type, method));
  1432. }
  1433. if (useCache) {
  1434. lock (_extensionMethodsCache) {
  1435. _extensionMethodsCache[assembly] = result;
  1436. }
  1437. }
  1438. return EnumerateExtensionMethods(result);
  1439. }
  1440. // TODO: GetVisibleExtensionMethods(Hashset<string> namespaces, Type type, string methodName) : IEnumerable<MethodInfo> {}
  1441. private static IEnumerable<KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>> EnumerateExtensionMethods(Dictionary<string, List<ExtensionMethodInfo>> dict) {
  1442. if (dict != null) {
  1443. foreach (var entry in dict) {
  1444. yield return new KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>(entry.Key, new ReadOnlyCollection<ExtensionMethodInfo>(entry.Value));
  1445. }
  1446. }
  1447. }
  1448. #endregion
  1449. #region Generic Types
  1450. internal static Dictionary<Type, Type> BindGenericParameters(Type/*!*/ openType, Type/*!*/ closedType, bool ignoreUnboundParameters) {
  1451. var binding = new Dictionary<Type, Type>();
  1452. BindGenericParameters(openType, closedType, (parameter, type) => {
  1453. Type existing;
  1454. if (binding.TryGetValue(parameter, out existing)) {
  1455. return type == existing;
  1456. }
  1457. binding[parameter] = type;
  1458. return true;
  1459. });
  1460. return ConstraintsViolated(binding, ignoreUnboundParameters) ? null : binding;
  1461. }
  1462. /// <summary>
  1463. /// Binds occurances of generic parameters in <paramref name="openType"/> against corresponding types in <paramref name="closedType"/>.
  1464. /// Invokes <paramref name="binder"/>(parameter, type) for each such binding.
  1465. /// Returns false if the <paramref name="openType"/> is structurally different from <paramref name="closedType"/> or if the binder returns false.
  1466. /// </summary>
  1467. internal static bool BindGenericParameters(Type/*!*/ openType, Type/*!*/ closedType, Func<Type, Type, bool>/*!*/ binder) {
  1468. if (openType.IsGenericParameter) {
  1469. return binder(openType, closedType);
  1470. }
  1471. if (openType.IsArray) {
  1472. if (!closedType.IsArray) {
  1473. return false;
  1474. }
  1475. return BindGenericParameters(openType.GetElementType(), closedType.GetElementType(), binder);
  1476. }
  1477. if (!openType.IsGenericType() || !closedType.IsGenericType()) {
  1478. return openType == closedType;
  1479. }
  1480. if (openType.GetGenericTypeDefinition() != closedType.GetGenericTypeDefinition()) {
  1481. return false;
  1482. }
  1483. Type[] closedArgs = closedType.GetGenericArguments();
  1484. Type[] openArgs = openType.GetGenericArguments();
  1485. for (int i = 0; i < openArgs.Length; i++) {
  1486. if (!BindGenericParameters(openArgs[i], closedArgs[i], binder)) {
  1487. return false;
  1488. }
  1489. }
  1490. return true;
  1491. }
  1492. internal static bool ConstraintsViolated(Dictionary<Type, Type>/*!*/ binding, bool ignoreUnboundParameters) {
  1493. foreach (var entry in binding) {
  1494. if (ConstraintsViolated(entry.Key, entry.Value, binding, ignoreUnboundParameters)) {
  1495. return true;
  1496. }
  1497. }
  1498. return false;
  1499. }
  1500. internal static bool ConstraintsViolated(Type/*!*/ genericParameter, Type/*!*/ closedType, Dictionary<Type, Type>/*!*/ binding, bool ignoreUnboundParameters) {
  1501. if ((genericParameter.GetGenericParameterAttributes() & GenericParameterAttributes.ReferenceTypeConstraint) != 0 && closedType.IsValueType()) {
  1502. // value type to parameter type constrained as class
  1503. return true;
  1504. }
  1505. if ((genericParameter.GetGenericParameterAttributes() & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0 &&
  1506. (!closedType.IsValueType() || (closedType.IsGenericType() && closedType.GetGenericTypeDefinition() == typeof(Nullable<>)))) {
  1507. // nullable<T> or class/interface to parameter type constrained as struct
  1508. return true;
  1509. }
  1510. if ((genericParameter.GetGenericParameterAttributes() & GenericParameterAttributes.DefaultConstructorConstraint) != 0 &&
  1511. (!closedType.IsValueType() && closedType.GetConstructor(ReflectionUtils.EmptyTypes) == null)) {
  1512. // reference type w/o a default constructor to type constrianed as new()
  1513. return true;
  1514. }
  1515. Type[] constraints = genericParameter.GetGenericParameterConstraints();
  1516. for (int i = 0; i < constraints.Length; i++) {
  1517. Type instantiation = InstantiateConstraint(constraints[i], binding);
  1518. if (instantiation == null) {
  1519. if (ignoreUnboundParameters) {
  1520. continue;
  1521. } else {
  1522. return true;
  1523. }
  1524. }
  1525. if (!instantiation.IsAssignableFrom(closedType)) {
  1526. return true;
  1527. }
  1528. }
  1529. return false;
  1530. }
  1531. internal static Type InstantiateConstraint(Type/*!*/ constraint, Dictionary<Type, Type>/*!*/ binding) {
  1532. Debug.Assert(!constraint.IsArray && !constraint.IsByRef && !constraint.IsGenericTypeDefinition());
  1533. if (!constraint.ContainsGenericParameters()) {
  1534. return constraint;
  1535. }
  1536. Type closedType;
  1537. if (constraint.IsGenericParameter) {
  1538. return binding.TryGetValue(constraint, out closedType) ? closedType : null;
  1539. }
  1540. Type[] args = constraint.GetGenericArguments();
  1541. for (int i = 0; i < args.Length; i++) {
  1542. if ((args[i] = InstantiateConstraint(args[i], binding)) == null) {
  1543. return null;
  1544. }
  1545. }
  1546. return constraint.GetGenericTypeDefinition().MakeGenericType(args);
  1547. }
  1548. #endregion
  1549. }
  1550. public struct ExtensionMethodInfo : IEquatable<ExtensionMethodInfo> {
  1551. private readonly Type/*!*/ _extendedType; // cached type of the first parameter
  1552. private readonly MethodInfo/*!*/ _method;
  1553. internal ExtensionMethodInfo(Type/*!*/ extendedType, MethodInfo/*!*/ method) {
  1554. Assert.NotNull(extendedType, method);
  1555. _extendedType = extendedType;
  1556. _method = method;
  1557. }
  1558. public Type/*!*/ ExtendedType {
  1559. get { return _extendedType; }
  1560. }
  1561. public MethodInfo/*!*/ Method {
  1562. get { return _method; }
  1563. }
  1564. public override bool Equals(object obj) {
  1565. return obj is ExtensionMethodInfo && Equals((ExtensionMethodInfo)obj);
  1566. }
  1567. public bool Equals(ExtensionMethodInfo other) {
  1568. return _method.Equals(other._method);
  1569. }
  1570. public static bool operator ==(ExtensionMethodInfo self, ExtensionMethodInfo other) {
  1571. return self.Equals(other);
  1572. }
  1573. public static bool operator !=(ExtensionMethodInfo self, ExtensionMethodInfo other) {
  1574. return !self.Equals(other);
  1575. }
  1576. public override int GetHashCode() {
  1577. return _method.GetHashCode();
  1578. }
  1579. /// <summary>
  1580. /// Determines if a given type matches the type that the method extends.
  1581. /// The match might be non-trivial if the extended type is an open generic type with constraints.
  1582. /// </summary>
  1583. public bool IsExtensionOf(Type/*!*/ type) {
  1584. ContractUtils.RequiresNotNull(type, "type");
  1585. #if FEATURE_TYPE_EQUIVALENCE
  1586. if (type.IsEquivalentTo(ExtendedType)) {
  1587. return true;
  1588. }
  1589. #else
  1590. if (type == _extendedType) {
  1591. return true;
  1592. }
  1593. #endif
  1594. if (!_extendedType.GetTypeInfo().ContainsGenericParameters) {
  1595. return false;
  1596. }
  1597. //
  1598. // Ignores constraints that can't be instantiated given the information we have (type of the first parameter).
  1599. //
  1600. // For example,
  1601. // void Foo<S, T>(this S x, T y) where S : T;
  1602. //
  1603. // We make such methods available on all types.
  1604. // If they are not called with arguments that satisfy the constraint the overload resolver might fail.
  1605. //
  1606. return ReflectionUtils.BindGenericParameters(_extendedType, type, true) != null;
  1607. }
  1608. }
  1609. }