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