1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
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.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
16 #if FEATURE_METADATA_READER
17 using Microsoft.Scripting.Metadata;
21 using TypeInfo = System.Type;
25 using System.Collections.Generic;
26 using System.Collections.ObjectModel;
27 using System.Diagnostics;
29 using System.Reflection;
31 using System.Reflection.Emit;
33 using System.Runtime.CompilerServices;
34 using System.Security;
36 using System.Runtime.InteropServices;
38 using System.Linq.Expressions;
40 using Microsoft.Scripting.Generation;
41 using Microsoft.Scripting.Runtime;
42 using Microsoft.Scripting.Utils;
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() {
56 public enum TypeCode {
78 namespace System.Reflection {
80 public enum BindingFlags {
81 /// <summary>Specifies that instance members are to be included in the search.</summary>
83 /// <summary>Specifies that static members are to be included in the search.</summary>
85 /// <summary>Specifies that public members are to be included in the search.</summary>
87 /// <summary>Specifies that non-public members are to be included in the search.</summary>
92 namespace System.Reflection {
93 public static class RuntimeReflectionExtensions {
94 public static MethodInfo GetRuntimeBaseDefinition(this MethodInfo method) {
95 return method.GetBaseDefinition();
98 public static IEnumerable<MethodInfo> GetRuntimeMethods(this Type type) {
99 return type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
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
110 /// The Default Parameter Value Attribute.
112 public sealed class DefaultParameterValueAttribute : Attribute
114 private readonly object _value;
118 get { return _value; }
124 /// <param name="value">The value.</param>
125 public DefaultParameterValueAttribute(object value)
132 [AttributeUsage(AttributeTargets.Parameter, Inherited = false), ComVisible(true)]
133 public sealed class OptionalAttribute : Attribute {
138 public static class ReflectionUtils {
139 #region Accessibility
141 public static BindingFlags AllMembers = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
143 public static bool IsPublic(this PropertyInfo property) {
144 return property.GetGetMethod(nonPublic: false) != null
145 || property.GetSetMethod(nonPublic: false) != null;
148 public static bool IsStatic(this PropertyInfo property) {
149 var getter = property.GetGetMethod(nonPublic: true);
150 var setter = property.GetSetMethod(nonPublic: true);
152 return getter != null && getter.IsStatic
153 || setter != null && setter.IsStatic;
156 public static bool IsStatic(this EventInfo evnt) {
157 var add = evnt.GetAddMethod(nonPublic: true);
158 var remove = evnt.GetRemoveMethod(nonPublic: true);
160 return add != null && add.IsStatic
161 || remove != null && remove.IsStatic;
164 public static bool IsPrivate(this PropertyInfo property) {
165 var getter = property.GetGetMethod(nonPublic: true);
166 var setter = property.GetSetMethod(nonPublic: true);
168 return (getter == null || getter.IsPrivate)
169 && (setter == null || setter.IsPrivate);
172 public static bool IsPrivate(this EventInfo evnt) {
173 var add = evnt.GetAddMethod(nonPublic: true);
174 var remove = evnt.GetRemoveMethod(nonPublic: true);
176 return (add == null || add.IsPrivate)
177 && (remove == null || remove.IsPrivate);
180 private static bool MatchesFlags(ConstructorInfo member, BindingFlags flags) {
182 ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
183 ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
186 private static bool MatchesFlags(MethodInfo member, BindingFlags flags) {
188 ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
189 ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
192 private static bool MatchesFlags(FieldInfo member, BindingFlags flags) {
194 ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
195 ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
198 private static bool MatchesFlags(PropertyInfo member, BindingFlags flags) {
200 ((member.IsPublic() ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
201 ((member.IsStatic() ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
204 private static bool MatchesFlags(EventInfo member, BindingFlags flags) {
205 var add = member.GetAddMethod();
206 var remove = member.GetRemoveMethod();
207 var raise = member.GetRaiseMethod();
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;
213 ((isPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
214 ((isStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
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;
222 private static bool MatchesFlags(MemberInfo member, BindingFlags flags) {
223 ConstructorInfo ctor;
227 PropertyInfo property;
229 if ((method = member as MethodInfo) != null) {
230 return MatchesFlags(method, flags);
233 if ((field = member as FieldInfo) != null) {
234 return MatchesFlags(field, flags);
237 if ((ctor = member as ConstructorInfo) != null) {
238 return MatchesFlags(ctor, flags);
241 if ((evnt = member as EventInfo) != null) {
242 return MatchesFlags(evnt, flags);
245 if ((property = member as PropertyInfo) != null) {
246 return MatchesFlags(property, flags);
249 return MatchesFlags((TypeInfo)member, flags);
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));
257 public static IEnumerable<MemberInfo> WithBindingFlags(this IEnumerable<MemberInfo> members, BindingFlags flags) {
258 return members.WithBindingFlags(MatchesFlags, flags);
261 public static IEnumerable<MethodInfo> WithBindingFlags(this IEnumerable<MethodInfo> members, BindingFlags flags) {
262 return members.WithBindingFlags(MatchesFlags, flags);
265 public static IEnumerable<ConstructorInfo> WithBindingFlags(this IEnumerable<ConstructorInfo> members, BindingFlags flags) {
266 return members.WithBindingFlags(MatchesFlags, flags);
269 public static IEnumerable<FieldInfo> WithBindingFlags(this IEnumerable<FieldInfo> members, BindingFlags flags) {
270 return members.WithBindingFlags(MatchesFlags, flags);
273 public static IEnumerable<PropertyInfo> WithBindingFlags(this IEnumerable<PropertyInfo> members, BindingFlags flags) {
274 return members.WithBindingFlags(MatchesFlags, flags);
277 public static IEnumerable<EventInfo> WithBindingFlags(this IEnumerable<EventInfo> members, BindingFlags flags) {
278 return members.WithBindingFlags(MatchesFlags, flags);
281 public static IEnumerable<TypeInfo> WithBindingFlags(this IEnumerable<TypeInfo> members, BindingFlags flags) {
282 return members.WithBindingFlags(MatchesFlags, flags);
285 public static MemberInfo WithBindingFlags(this MemberInfo member, BindingFlags flags) {
286 return member != null && MatchesFlags(member, flags) ? member : null;
289 public static MethodInfo WithBindingFlags(this MethodInfo member, BindingFlags flags) {
290 return member != null && MatchesFlags(member, flags) ? member : null;
293 public static ConstructorInfo WithBindingFlags(this ConstructorInfo member, BindingFlags flags) {
294 return member != null && MatchesFlags(member, flags) ? member : null;
297 public static FieldInfo WithBindingFlags(this FieldInfo member, BindingFlags flags) {
298 return member != null && MatchesFlags(member, flags) ? member : null;
301 public static PropertyInfo WithBindingFlags(this PropertyInfo member, BindingFlags flags) {
302 return member != null && MatchesFlags(member, flags) ? member : null;
305 public static EventInfo WithBindingFlags(this EventInfo member, BindingFlags flags) {
306 return member != null && MatchesFlags(member, flags) ? member : null;
309 public static TypeInfo WithBindingFlags(this TypeInfo member, BindingFlags flags) {
310 return member != null && MatchesFlags(member, flags) ? member : null;
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) {
324 for (int i = 0; i < ps.Length; i++) {
325 if (parameterTypes[i] != ps[i].ParameterType) {
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) {
341 for (int i = 0; i < ps.Length; i++) {
342 if (parameterTypes[i] != ps[i].ParameterType) {
353 #region Member Inheritance
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.
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.
372 // NOTE: Following GetXxx only implement overriding, not hiding specified by hide-by-name or hide-by-name-and-signature flags.
374 public static IEnumerable<MethodInfo> GetInheritedMethods(this Type type, string name = null, bool flattenHierarchy = false) {
375 while (type.IsGenericParameter) {
376 type = type.GetBaseType();
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;
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))) {
394 } else if (member.DeclaringType == reflectedType) {
396 } else if (!member.IsPrivate && (!member.IsStatic || flattenHierarchy)) {
403 public static IEnumerable<PropertyInfo> GetInheritedProperties(this Type type, string name = null, bool flattenHierarchy = false) {
404 while (type.IsGenericParameter) {
405 type = type.GetBaseType();
408 var baseDefinitions = new HashSet<MethodInfo>(ReferenceEqualityComparer<MethodInfo>.Instance);
409 foreach (var ancestor in type.Ancestors()) {
411 var declaredProperty = ancestor.GetDeclaredProperty(name);
412 if (declaredProperty != null && IncludeProperty(declaredProperty, type, baseDefinitions, flattenHierarchy)) {
413 yield return declaredProperty;
416 foreach (var declaredProperty in ancestor.GetDeclaredProperties()) {
417 if (IncludeProperty(declaredProperty, type, baseDefinitions, flattenHierarchy)) {
418 yield return declaredProperty;
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);
437 MethodInfo virtualAccessor;
438 if (getter != null && getter.IsVirtual) {
439 virtualAccessor = getter;
440 } else if (setter != null && setter.IsVirtual) {
441 virtualAccessor = setter;
443 virtualAccessor = null;
446 if (virtualAccessor != null) {
447 if (baseDefinitions.Add(RuntimeReflectionExtensions.GetRuntimeBaseDefinition(virtualAccessor))) {
450 } else if (member.DeclaringType == reflectedType) {
452 } else if (!member.IsPrivate() && (!member.IsStatic() || flattenHierarchy)) {
459 public static IEnumerable<EventInfo> GetInheritedEvents(this Type type, string name = null, bool flattenHierarchy = false) {
460 while (type.IsGenericParameter) {
461 type = type.GetBaseType();
464 var baseDefinitions = new HashSet<MethodInfo>(ReferenceEqualityComparer<MethodInfo>.Instance);
465 foreach (var ancestor in type.Ancestors()) {
467 var declaredEvent = ancestor.GetDeclaredEvent(name);
468 if (declaredEvent != null && IncludeEvent(declaredEvent, type, baseDefinitions, flattenHierarchy)) {
469 yield return declaredEvent;
472 foreach (var declaredEvent in ancestor.GetDeclaredEvents()) {
473 if (IncludeEvent(declaredEvent, type, baseDefinitions, flattenHierarchy)) {
474 yield return declaredEvent;
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);
485 // TOOD: fire method?
487 MethodInfo virtualAccessor;
488 if (add != null && add.IsVirtual) {
489 virtualAccessor = add;
490 } else if (remove != null && remove.IsVirtual) {
491 virtualAccessor = remove;
493 virtualAccessor = null;
496 if (virtualAccessor != null) {
497 if (baseDefinitions.Add(RuntimeReflectionExtensions.GetRuntimeBaseDefinition(virtualAccessor))) {
500 } else if (member.DeclaringType == reflectedType) {
502 } else if (!member.IsPrivate() && (!member.IsStatic() || flattenHierarchy)) {
509 public static IEnumerable<FieldInfo> GetInheritedFields(this Type type, string name = null, bool flattenHierarchy = false) {
510 while (type.IsGenericParameter) {
511 type = type.GetBaseType();
514 foreach (var ancestor in type.Ancestors()) {
516 var declaredField = ancestor.GetDeclaredField(name);
517 if (declaredField != null && IncludeField(declaredField, type, flattenHierarchy)) {
518 yield return declaredField;
521 foreach (var declaredField in ancestor.GetDeclaredFields()) {
522 if (IncludeField(declaredField, type, flattenHierarchy)) {
523 yield return declaredField;
530 private static bool IncludeField(FieldInfo member, Type reflectedType, bool flattenHierarchy) {
531 if (member.DeclaringType == reflectedType) {
533 } else if (!member.IsPrivate && (!member.IsStatic || flattenHierarchy)) {
540 public static IEnumerable<MemberInfo> GetInheritedMembers(this Type type, string name = null, bool flattenHierarchy = false) {
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>())));
548 return result.Concat<MemberInfo>(
549 type.GetDeclaredConstructors().Cast<ConstructorInfo, MemberInfo>().Concat(
550 type.GetDeclaredNestedTypes().Cast<TypeInfo, MemberInfo>()));
553 var nestedType = type.GetDeclaredNestedType(name);
554 return (nestedType != null) ? result.Concat(new[] { nestedType }) : result;
559 #region Declared Members
561 public static IEnumerable<ConstructorInfo> GetDeclaredConstructors(this Type type) {
563 return type.GetTypeInfo().DeclaredConstructors;
565 return type.GetConstructors(BindingFlags.DeclaredOnly | AllMembers);
570 public static ConstructorInfo GetConstructor(this Type type, Type[] parameterTypes) {
571 return type.GetDeclaredConstructors().Where(ci => !ci.IsStatic && ci.IsPublic).WithSignature(parameterTypes).SingleOrDefault();
575 public static IEnumerable<MethodInfo> GetDeclaredMethods(this Type type, string name = null) {
578 return type.GetTypeInfo().DeclaredMethods;
580 return type.GetTypeInfo().GetDeclaredMethods(name);
584 return type.GetMethods(BindingFlags.DeclaredOnly | AllMembers);
586 return type.GetMember(name, MemberTypes.Method, BindingFlags.DeclaredOnly | AllMembers).OfType<MethodInfo>();
591 public static IEnumerable<PropertyInfo> GetDeclaredProperties(this Type type) {
593 return type.GetTypeInfo().DeclaredProperties;
595 return type.GetProperties(BindingFlags.DeclaredOnly | AllMembers);
599 public static PropertyInfo GetDeclaredProperty(this Type type, string name) {
600 Debug.Assert(name != null);
602 return type.GetTypeInfo().GetDeclaredProperty(name);
604 return type.GetProperty(name, BindingFlags.DeclaredOnly | AllMembers);
608 public static IEnumerable<EventInfo> GetDeclaredEvents(this Type type) {
610 return type.GetTypeInfo().DeclaredEvents;
612 return type.GetEvents(BindingFlags.DeclaredOnly | AllMembers);
616 public static EventInfo GetDeclaredEvent(this Type type, string name) {
617 Debug.Assert(name != null);
619 return type.GetTypeInfo().GetDeclaredEvent(name);
621 return type.GetEvent(name, BindingFlags.DeclaredOnly | AllMembers);
625 public static IEnumerable<FieldInfo> GetDeclaredFields(this Type type) {
627 return type.GetTypeInfo().DeclaredFields;
629 return type.GetFields(BindingFlags.DeclaredOnly | AllMembers);
633 public static FieldInfo GetDeclaredField(this Type type, string name) {
634 Debug.Assert(name != null);
636 return type.GetTypeInfo().GetDeclaredField(name);
638 return type.GetField(name, BindingFlags.DeclaredOnly | AllMembers);
642 public static IEnumerable<TypeInfo> GetDeclaredNestedTypes(this Type type) {
644 return type.GetTypeInfo().DeclaredNestedTypes;
646 return type.GetNestedTypes(BindingFlags.DeclaredOnly | AllMembers);
650 public static TypeInfo GetDeclaredNestedType(this Type type, string name) {
651 Debug.Assert(name != null);
653 return type.GetTypeInfo().GetDeclaredNestedType(name);
655 return type.GetNestedType(name, BindingFlags.DeclaredOnly | AllMembers);
659 public static IEnumerable<MemberInfo> GetDeclaredMembers(this Type type, string name = null) {
661 var info = type.GetTypeInfo();
663 return info.DeclaredMembers;
665 return GetDeclaredMembersWithName(info, name);
669 return type.GetMembers(BindingFlags.DeclaredOnly | AllMembers);
671 return type.GetMember(name, BindingFlags.DeclaredOnly | AllMembers);
677 private static IEnumerable<MemberInfo> GetDeclaredMembersWithName(TypeInfo info, string name) {
680 if ((member = info.GetDeclaredMethod(name)) != null) {
684 if ((member = info.GetDeclaredField(name)) != null) {
688 if ((member = info.GetDeclaredProperty(name)) != null) {
692 if ((member = info.GetDeclaredEvent(name)) != null) {
696 if ((member = info.GetDeclaredNestedType(name)) != null) {
706 public static TypeCode GetTypeCode(this Enum e) {
707 return GetTypeCode(Enum.GetUnderlyingType(e.GetType()));
710 // TODO: reduce to numeric types?
711 public static TypeCode GetTypeCode(this Type type) {
712 if (type == typeof(int)) {
713 return TypeCode.Int32;
715 if (type == typeof(sbyte)) {
716 return TypeCode.SByte;
718 if (type == typeof(short)) {
719 return TypeCode.Int16;
721 if (type == typeof(long)) {
722 return TypeCode.Int64;
724 if (type == typeof(uint)) {
725 return TypeCode.UInt32;
727 if (type == typeof(byte)) {
728 return TypeCode.Byte;
730 if (type == typeof(ushort)) {
731 return TypeCode.UInt16;
733 if (type == typeof(ulong)) {
734 return TypeCode.UInt64;
736 if (type == typeof(bool)) {
737 return TypeCode.Boolean;
739 if (type == typeof(char)) {
740 return TypeCode.Char;
743 // TODO: do we need this?
744 if (type == typeof(string)) {
745 return TypeCode.String;
747 if (type == typeof(bool)) {
748 return TypeCode.Boolean;
750 if (type == typeof(double)) {
751 return TypeCode.Double;
753 if (type == typeof(float)) {
754 return TypeCode.Single;
756 if (type == typeof(decimal)) {
757 return TypeCode.Decimal;
759 if (type == typeof(DateTime)) {
760 return TypeCode.DateTime;
762 return TypeCode.Object;
765 public static IEnumerable<Type> GetImplementedInterfaces(this Type type) {
766 return type.GetTypeInfo().ImplementedInterfaces;
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;
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;
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;
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;
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;
794 public static MethodInfo GetMethod(this Type type, string name) {
795 return type.GetTypeInfo().GetDeclaredMethod(name);
798 // TODO: FlattenHierarchy
800 public static MethodInfo GetMethod(this Type type, string name, Type[] parameterTypes) {
801 return type.GetTypeInfo().GetDeclaredMethods(name).WithSignature(parameterTypes).Single();
804 public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags) {
805 return type.GetMethods(name, bindingFlags).Single();
808 private static IEnumerable<MethodInfo> GetMethods(this Type type, string name, BindingFlags bindingFlags) {
809 return type.GetTypeInfo().GetDeclaredMethods(name).WithBindingFlags(bindingFlags);
812 public static MethodInfo GetMethod(this Delegate d) {
813 return d.GetMethodInfo();
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;
822 public static Type[] GetGenericTypeArguments(this Type type) {
823 return type.GetTypeInfo().GenericTypeArguments;
826 public static Type[] GetGenericTypeParameters(this Type type) {
827 return type.GetTypeInfo().GenericTypeParameters;
830 public static bool IsAssignableFrom(this Type type, Type other) {
831 return type.GetTypeInfo().IsAssignableFrom(other.GetTypeInfo());
834 public static Type[] GetGenericParameterConstraints(this Type type) {
835 return type.GetTypeInfo().GetGenericParameterConstraints();
838 public static bool IsSubclassOf(this Type type, Type other) {
839 return type.GetTypeInfo().IsSubclassOf(other);
842 public static IEnumerable<Type> GetInterfaces(this Type type) {
843 return type.GetTypeInfo().ImplementedInterfaces;
846 public static Type[] GetRequiredCustomModifiers(this ParameterInfo parameter) {
850 public static Type[] GetOptionalCustomModifiers(this ParameterInfo parameter) {
854 public static IEnumerable<Module> GetModules(this Assembly assembly) {
855 return assembly.Modules;
858 private static string GetDefaultMemberName(this Type type) {
859 foreach (var ancestor in type.Ancestors()) {
860 var attr = ancestor.GetTypeInfo().GetCustomAttributes<DefaultMemberAttribute>().SingleOrDefault();
862 return attr.MemberName;
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);
875 return Enumerable.Empty<MemberInfo>();
878 public static Type[] GetGenericTypeArguments(this Type type) {
879 return type.IsGenericType && !type.IsGenericTypeDefinition ? type.GetTypeInfo().GetGenericArguments() : null;
882 public static Type[] GetGenericTypeParameters(this Type type) {
883 return type.IsGenericTypeDefinition ? type.GetTypeInfo().GetGenericArguments() : null;
886 public static IEnumerable<Module> GetModules(this Assembly assembly) {
887 return assembly.GetModules();
890 public static IEnumerable<Type> GetImplementedInterfaces(this Type type) {
891 return type.GetInterfaces();
894 public static TypeCode GetTypeCode(this Type type) {
895 return Type.GetTypeCode(type);
898 public static MethodInfo GetMethodInfo(this Delegate d) {
902 public static bool IsDefined(this Assembly assembly, Type attributeType) {
903 return assembly.IsDefined(attributeType, false);
906 public static T GetCustomAttribute<T>(this Assembly assembly, bool inherit = false) where T : Attribute {
907 return (T)Attribute.GetCustomAttribute(assembly, typeof(T), inherit);
910 public static T GetCustomAttribute<T>(this MemberInfo member, bool inherit = false) where T : Attribute {
911 return (T)Attribute.GetCustomAttribute(member, typeof(T), inherit);
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>();
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>();
923 public static bool ContainsGenericParameters(this Type type) {
924 return type.GetTypeInfo().ContainsGenericParameters;
927 public static bool IsInterface(this Type type) {
928 return type.GetTypeInfo().IsInterface;
931 public static bool IsClass(this Type type) {
932 return type.GetTypeInfo().IsClass;
935 public static bool IsGenericType(this Type type) {
936 return type.GetTypeInfo().IsGenericType;
939 public static bool IsGenericTypeDefinition(this Type type) {
940 return type.GetTypeInfo().IsGenericTypeDefinition;
943 public static bool IsSealed(this Type type) {
944 return type.GetTypeInfo().IsSealed;
947 public static bool IsAbstract(this Type type) {
948 return type.GetTypeInfo().IsAbstract;
951 public static bool IsPublic(this Type type) {
952 return type.GetTypeInfo().IsPublic;
955 public static bool IsVisible(this Type type) {
956 return type.GetTypeInfo().IsVisible;
959 public static Type GetBaseType(this Type type) {
960 return type.GetTypeInfo().BaseType;
963 public static bool IsValueType(this Type type) {
964 return type.GetTypeInfo().IsValueType;
967 public static bool IsEnum(this Type type) {
968 return type.GetTypeInfo().IsEnum;
971 public static bool IsPrimitive(this Type type) {
972 return type.GetTypeInfo().IsPrimitive;
975 public static GenericParameterAttributes GetGenericParameterAttributes(this Type type) {
976 return type.GetTypeInfo().GenericParameterAttributes;
979 public static Type[] EmptyTypes = new Type[0];
981 public static object GetRawConstantValue(this FieldInfo field) {
982 if (!field.IsLiteral) {
983 throw new ArgumentException(field + " not a literal.");
986 object value = field.GetValue(null);
987 return field.FieldType.IsEnum() ? UnwrapEnumValue(value) : value;
991 /// Converts a boxed enum value to the underlying integer value.
993 public static object UnwrapEnumValue(object value) {
995 throw new ArgumentNullException("value");
998 switch (value.GetType().GetTypeCode()) {
1000 return System.Convert.ToByte(value);
1002 case TypeCode.Int16:
1003 return System.Convert.ToInt16(value);
1005 case TypeCode.Int32:
1006 return System.Convert.ToInt32(value);
1008 case TypeCode.Int64:
1009 return System.Convert.ToInt64(value);
1011 case TypeCode.SByte:
1012 return System.Convert.ToSByte(value);
1014 case TypeCode.UInt16:
1015 return System.Convert.ToUInt16(value);
1017 case TypeCode.UInt32:
1018 return System.Convert.ToUInt32(value);
1020 case TypeCode.UInt64:
1021 return System.Convert.ToUInt64(value);
1024 throw new ArgumentException("Value must be a boxed enum.", "value");
1031 #if FEATURE_ASSEMBLYBUILDER_DEFINEDYNAMICASSEMBLY
1032 public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) {
1033 return AssemblyBuilder.DefineDynamicAssembly(name, access);
1036 public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) {
1037 return AppDomain.CurrentDomain.DefineDynamicAssembly(name, access);
1040 #if !FEATURE_PDBEMIT
1041 public static ModuleBuilder DefineDynamicModule(this AssemblyBuilder assembly, string name, bool emitDebugInfo) {
1043 return assembly.DefineDynamicModule(name);
1048 #region Signature and Type Formatting
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 = '`';
1056 public static StringBuilder FormatSignature(StringBuilder result, MethodBase method) {
1057 return FormatSignature(result, method, (t) => t.FullName);
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");
1065 MethodInfo methodInfo = method as MethodInfo;
1066 if (methodInfo != null) {
1067 FormatTypeName(result, methodInfo.ReturnType, nameDispenser);
1072 MethodBuilder builder = method as MethodBuilder;
1073 if (builder != null) {
1074 result.Append(builder.Signature);
1078 ConstructorBuilder cb = method as ConstructorBuilder;
1080 result.Append(cb.Signature);
1084 FormatTypeName(result, method.DeclaringType, nameDispenser);
1085 result.Append("::");
1086 result.Append(method.Name);
1088 if (!method.IsConstructor) {
1089 FormatTypeArgs(result, method.GetGenericArguments(), nameDispenser);
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)) {
1101 result.Append(ps[i].Name);
1113 public static StringBuilder FormatTypeName(StringBuilder result, Type type) {
1114 return FormatTypeName(result, type, (t) => t.FullName);
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");
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);
1128 Type[] typeArgs = type.GetGenericArguments();
1129 if (type.IsGenericTypeDefinition()) {
1131 result.Append(',', typeArgs.Length - 1);
1134 FormatTypeArgs(result, typeArgs, nameDispenser);
1136 } else if (type.IsGenericParameter) {
1137 result.Append(type.Name);
1139 // cut namespace off:
1140 result.Append(nameDispenser(type).Replace('+', '.'));
1145 public static StringBuilder FormatTypeArgs(StringBuilder result, Type[] types) {
1146 return FormatTypeArgs(result, types, (t) => t.FullName);
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");
1154 if (types.Length > 0) {
1157 for (int i = 0; i < types.Length; i++) {
1158 if (i > 0) result.Append(", ");
1159 FormatTypeName(result, types[i], nameDispenser);
1167 internal static string ToValidTypeName(string str) {
1168 if (String.IsNullOrEmpty(str)) {
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] == '\\') {
1178 return sb.ToString();
1181 public static string GetNormalizedTypeName(Type type) {
1182 string name = type.Name;
1183 if (type.IsGenericType()) {
1184 return GetNormalizedTypeName(name);
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);
1198 #region Delegates and Dynamic Methods
1202 /// Creates an open delegate for the given (dynamic)method.
1204 public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType) {
1205 return CreateDelegate(methodInfo, delegateType, null);
1209 /// Creates a closed delegate for the given (dynamic)method.
1211 public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
1212 return Delegate.CreateDelegate(delegateType, target, methodInfo);
1216 /// Creates an open delegate for the given (dynamic)method.
1218 public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType) {
1219 return CreateDelegate(methodInfo, delegateType, null);
1223 /// Creates a closed delegate for the given (dynamic)method.
1225 public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
1227 DynamicMethod dm = methodInfo as DynamicMethod;
1229 return dm.CreateDelegate(delegateType, target);
1231 return Delegate.CreateDelegate(delegateType, target, methodInfo);
1236 public static bool IsDynamicMethod(MethodBase method) {
1237 return !PlatformAdaptationLayer.IsCompactFramework && IsDynamicMethodInternal(method);
1240 [MethodImpl(MethodImplOptions.NoInlining)]
1241 private static bool IsDynamicMethodInternal(MethodBase method) {
1242 return method is DynamicMethod;
1245 public static bool IsDynamicMethod(MethodBase method) {
1250 public static void GetDelegateSignature(Type delegateType, out ParameterInfo[] parameterInfos, out ParameterInfo returnInfo) {
1251 ContractUtils.RequiresNotNull(delegateType, "delegateType");
1253 MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
1254 ContractUtils.Requires(invokeMethod != null, "delegateType", Strings.InvalidDelegate);
1256 parameterInfos = invokeMethod.GetParameters();
1257 returnInfo = invokeMethod.ReturnParameter;
1261 /// Gets a Func of CallSite, object * paramCnt, object delegate type
1262 /// that's suitable for use in a non-strongly typed call site.
1264 public static Type GetObjectCallSiteDelegateType(int 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>);
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);
1289 return Snippets.Shared.DefineDelegate("InvokeDelegate" + paramCnt, typeof(object), paramTypes);
1291 throw new NotSupportedException("Signature not supported on this platform.");
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);
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
1307 return new DynamicMethod(name, returnType, parameterTypes, true);
1314 #region Methods and Parameters
1316 public static MethodBase[] GetMethodInfos(MemberInfo[] members) {
1317 return ArrayUtils.ConvertAll<MemberInfo, MethodBase>(
1319 delegate(MemberInfo inp) { return (MethodBase)inp; });
1322 public static Type[] GetParameterTypes(ParameterInfo[] parameterInfos) {
1323 return GetParameterTypes((IList<ParameterInfo>)parameterInfos);
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;
1334 public static Type GetReturnType(this MethodBase mi) {
1335 return (mi.IsConstructor) ? mi.DeclaringType : ((MethodInfo)mi).ReturnType;
1338 public static bool SignatureEquals(MethodInfo method, params Type[] requiredSignature) {
1339 ContractUtils.RequiresNotNull(method, "method");
1341 Type[] actualTypes = ReflectionUtils.GetParameterTypes(method.GetParameters());
1342 Debug.Assert(actualTypes.Length == requiredSignature.Length - 1);
1344 while (i < actualTypes.Length) {
1345 if (actualTypes[i] != requiredSignature[i]) return false;
1349 return method.ReturnType == requiredSignature[i];
1352 #if CLR2 && !SILVERLIGHT
1353 private static Type _ExtensionAttributeType;
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)) {
1363 #if CLR2 && !SILVERLIGHT
1364 if (_ExtensionAttributeType == null) {
1366 _ExtensionAttributeType = Assembly.Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
1367 .GetType("System.Runtime.CompilerServices.ExtensionAttribute");
1369 _ExtensionAttributeType = dlrExtension;
1373 if (_ExtensionAttributeType != dlrExtension) {
1374 return member.IsDefined(_ExtensionAttributeType, false);
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;
1386 /// Returns <c>true</c> if the specified parameter is mandatory, i.e. is not optional and doesn't have a default value.
1388 public static bool IsMandatory(this ParameterInfo pi) {
1389 return (pi.Attributes & ParameterAttributes.Optional) == 0 && !pi.HasDefaultValue();
1392 public static bool HasDefaultValue(this ParameterInfo pi) {
1393 #if !FEATURE_DEFAULT_PARAMETER_VALUE
1394 return pi.IsDefined(typeof(DefaultParameterValueAttribute), false);
1396 return (pi.Attributes & ParameterAttributes.HasDefault) != 0;
1400 public static bool ProhibitsNull(this ParameterInfo parameter) {
1401 return parameter.IsDefined(typeof(NotNullAttribute), false);
1404 public static bool ProhibitsNullItems(this ParameterInfo parameter) {
1405 return parameter.IsDefined(typeof(NotNullItemsAttribute), false);
1408 public static bool IsParamArray(this ParameterInfo parameter) {
1409 return parameter.IsDefined(typeof(ParamArrayAttribute), false);
1412 public static bool IsParamDictionary(this ParameterInfo parameter) {
1413 return parameter.IsDefined(typeof(ParamDictionaryAttribute), false);
1416 public static bool IsParamsMethod(MethodBase method) {
1417 return IsParamsMethod(method.GetParameters());
1420 public static bool IsParamsMethod(ParameterInfo[] pis) {
1421 foreach (ParameterInfo pi in pis) {
1422 if (pi.IsParamArray() || pi.IsParamDictionary()) return true;
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);
1433 var defaultValueAttribute = info.GetCustomAttributes(typeof(DefaultParameterValueAttribute), false);
1434 if (defaultValueAttribute.Length > 0) {
1435 return ((DefaultParameterValueAttribute)defaultValueAttribute[0]).Value;
1440 return info.DefaultValue;
1449 /// Yields all ancestors of the given type including the type itself.
1450 /// Does not include implemented interfaces.
1452 public static IEnumerable<Type> Ancestors(this Type type) {
1455 type = type.GetTypeInfo().BaseType;
1456 } while (type != null);
1460 /// Like Type.GetInterfaces, but only returns the interfaces implemented by this type
1461 /// and not its parents.
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);
1474 internal static IEnumerable<TypeInfo> GetAllTypesFromAssembly(Assembly asm) {
1476 #if SILVERLIGHT // ReflectionTypeLoadException
1478 return asm.GetTypes();
1479 } catch (Exception) {
1480 return ReflectionUtils.EmptyTypes;
1483 return asm.DefinedTypes;
1485 foreach (Module module in asm.GetModules()) {
1488 moduleTypes = module.GetTypes();
1489 } catch (ReflectionTypeLoadException e) {
1490 moduleTypes = e.Types;
1493 foreach (var type in moduleTypes) {
1502 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
1503 internal static IEnumerable<TypeInfo> GetAllTypesFromAssembly(Assembly assembly, bool includePrivateTypes) {
1504 ContractUtils.RequiresNotNull(assembly, "assembly");
1506 if (includePrivateTypes) {
1507 return GetAllTypesFromAssembly(assembly);
1512 return assembly.ExportedTypes.Select(t => t.GetTypeInfo());
1514 return assembly.GetExportedTypes();
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.
1523 return GetAllTypesFromAssembly(assembly).Where(type => type.IsPublic);
1528 #region Type Builder
1531 #if WIN8 // TODO: what is ReservedMask?
1532 private const MethodAttributes MethodAttributesToEraseInOveride = MethodAttributes.Abstract | (MethodAttributes)0xD000;
1534 private const MethodAttributes MethodAttributesToEraseInOveride = MethodAttributes.Abstract | MethodAttributes.ReservedMask;
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;
1543 if ((extra & MethodAttributes.MemberAccessMask) != 0) {
1544 // remove existing member access, add new member access
1545 finalAttrs &= ~MethodAttributes.MemberAccessMask;
1546 finalAttrs |= extra;
1549 MethodBuilder impl = tb.DefineMethod(decl.Name, finalAttrs, decl.CallingConvention);
1550 CopyMethodSignature(decl, impl, false);
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;
1560 #if FEATURE_CUSTOM_MODIFIERS
1561 returnRequiredModifiers = from.ReturnParameter.GetRequiredCustomModifiers();
1562 returnOptionalModifiers = from.ReturnParameter.GetOptionalCustomModifiers();
1564 for (int i = 0; i < paramInfos.Length; i++) {
1565 if (substituteDeclaringType && paramInfos[i].ParameterType == from.DeclaringType) {
1566 parameterTypes[i] = to.DeclaringType;
1568 parameterTypes[i] = paramInfos[i].ParameterType;
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][];
1578 parameterRequiredModifiers[i] = mods;
1581 mods = paramInfos[i].GetOptionalCustomModifiers();
1582 if (mods.Length > 0) {
1583 if (parameterOptionalModifiers == null) {
1584 parameterOptionalModifiers = new Type[paramInfos.Length][];
1587 parameterOptionalModifiers[i] = mods;
1593 from.ReturnType, returnRequiredModifiers, returnOptionalModifiers,
1594 parameterTypes, parameterRequiredModifiers, parameterOptionalModifiers
1597 CopyGenericMethodAttributes(from, to);
1599 for (int i = 0; i < paramInfos.Length; i++) {
1600 to.DefineParameter(i + 1, paramInfos[i].Attributes, paramInfos[i].Name);
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;
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());
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);
1623 builders[i].SetBaseTypeConstraint(constraint);
1626 if (interfaces.Count > 0) {
1627 builders[i].SetInterfaceConstraints(interfaces.ToArray());
1635 #region Extension Methods
1637 public static IEnumerable<MethodInfo> GetVisibleExtensionMethods(Assembly assembly) {
1638 #if FEATURE_METADATA_READER
1639 if (!assembly.IsDynamic && AppDomain.CurrentDomain.IsFullyTrusted) {
1641 return GetVisibleExtensionMethodsFast(assembly);
1642 } catch (SecurityException) {
1643 // full-demand can still fail if there is a partial trust domain on the stack
1647 return GetVisibleExtensionMethodsSlow(assembly);
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);
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) &&
1668 type.IsDefined(ea, false)) {
1670 foreach (MethodInfo method in type.AsType().GetDeclaredMethods()) {
1671 if (method.IsPublic && method.IsStatic && method.IsDefined(ea, false)) {
1672 yield return method;
1680 // Value is null if there are no extension methods in the assembly.
1681 private static Dictionary<Assembly, Dictionary<string, List<ExtensionMethodInfo>>> _extensionMethodsCache;
1684 /// Enumerates extension methods in given assembly. Groups the methods by declaring namespace.
1685 /// Uses a global cache if <paramref name="useCache"/> is true.
1687 public static IEnumerable<KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>> GetVisibleExtensionMethodGroups(Assembly/*!*/ assembly, bool useCache) {
1688 #if !CLR2 && FEATURE_REFEMIT
1689 useCache &= !assembly.IsDynamic;
1692 if (_extensionMethodsCache == null) {
1693 _extensionMethodsCache = new Dictionary<Assembly, Dictionary<string, List<ExtensionMethodInfo>>>();
1696 lock (_extensionMethodsCache) {
1697 Dictionary<string, List<ExtensionMethodInfo>> existing;
1698 if (_extensionMethodsCache.TryGetValue(assembly, out existing)) {
1699 return EnumerateExtensionMethods(existing);
1704 Dictionary<string, List<ExtensionMethodInfo>> result = null;
1705 foreach (MethodInfo method in ReflectionUtils.GetVisibleExtensionMethodsSlow(assembly)) {
1706 if (method.DeclaringType == null || method.DeclaringType.IsGenericTypeDefinition()) {
1710 var parameters = method.GetParameters();
1711 if (parameters.Length == 0) {
1715 Type type = parameters[0].ParameterType;
1716 if (type.IsByRef || type.IsPointer) {
1720 string ns = method.DeclaringType.Namespace ?? String.Empty;
1721 List<ExtensionMethodInfo> extensions = null;
1723 if (result == null) {
1724 result = new Dictionary<string, List<ExtensionMethodInfo>>();
1727 if (!result.TryGetValue(ns, out extensions)) {
1728 result.Add(ns, extensions = new List<ExtensionMethodInfo>());
1731 extensions.Add(new ExtensionMethodInfo(type, method));
1735 lock (_extensionMethodsCache) {
1736 _extensionMethodsCache[assembly] = result;
1740 return EnumerateExtensionMethods(result);
1743 // TODO: GetVisibleExtensionMethods(Hashset<string> namespaces, Type type, string methodName) : IEnumerable<MethodInfo> {}
1745 private static IEnumerable<KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>> EnumerateExtensionMethods(Dictionary<string, List<ExtensionMethodInfo>> dict) {
1747 foreach (var entry in dict) {
1748 yield return new KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>(entry.Key, new ReadOnlyCollection<ExtensionMethodInfo>(entry.Value));
1755 #region Generic Types
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) => {
1761 if (binding.TryGetValue(parameter, out existing)) {
1762 return type == existing;
1765 binding[parameter] = type;
1770 return ConstraintsViolated(binding, ignoreUnboundParameters) ? null : binding;
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.
1778 internal static bool BindGenericParameters(Type/*!*/ openType, Type/*!*/ closedType, Func<Type, Type, bool>/*!*/ binder) {
1779 if (openType.IsGenericParameter) {
1780 return binder(openType, closedType);
1783 if (openType.IsArray) {
1784 if (!closedType.IsArray) {
1787 return BindGenericParameters(openType.GetElementType(), closedType.GetElementType(), binder);
1790 if (!openType.IsGenericType() || !closedType.IsGenericType()) {
1791 return openType == closedType;
1794 if (openType.GetGenericTypeDefinition() != closedType.GetGenericTypeDefinition()) {
1798 Type[] closedArgs = closedType.GetGenericArguments();
1799 Type[] openArgs = openType.GetGenericArguments();
1801 for (int i = 0; i < openArgs.Length; i++) {
1802 if (!BindGenericParameters(openArgs[i], closedArgs[i], binder)) {
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)) {
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
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
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()
1838 Type[] constraints = genericParameter.GetGenericParameterConstraints();
1839 for (int i = 0; i < constraints.Length; i++) {
1840 Type instantiation = InstantiateConstraint(constraints[i], binding);
1842 if (instantiation == null) {
1843 if (ignoreUnboundParameters) {
1850 if (!instantiation.IsAssignableFrom(closedType)) {
1858 internal static Type InstantiateConstraint(Type/*!*/ constraint, Dictionary<Type, Type>/*!*/ binding) {
1859 Debug.Assert(!constraint.IsArray && !constraint.IsByRef && !constraint.IsGenericTypeDefinition());
1860 if (!constraint.ContainsGenericParameters()) {
1865 if (constraint.IsGenericParameter) {
1866 return binding.TryGetValue(constraint, out closedType) ? closedType : null;
1869 Type[] args = constraint.GetGenericArguments();
1870 for (int i = 0; i < args.Length; i++) {
1871 if ((args[i] = InstantiateConstraint(args[i], binding)) == null) {
1876 return constraint.GetGenericTypeDefinition().MakeGenericType(args);
1882 public struct ExtensionMethodInfo : IEquatable<ExtensionMethodInfo> {
1883 private readonly Type/*!*/ _extendedType; // cached type of the first parameter
1884 private readonly MethodInfo/*!*/ _method;
1886 internal ExtensionMethodInfo(Type/*!*/ extendedType, MethodInfo/*!*/ method) {
1887 Assert.NotNull(extendedType, method);
1888 _extendedType = extendedType;
1892 public Type/*!*/ ExtendedType {
1893 get { return _extendedType; }
1896 public MethodInfo/*!*/ Method {
1897 get { return _method; }
1900 public override bool Equals(object obj) {
1901 return obj is ExtensionMethodInfo && Equals((ExtensionMethodInfo)obj);
1904 public bool Equals(ExtensionMethodInfo other) {
1905 return _method.Equals(other._method);
1908 public static bool operator ==(ExtensionMethodInfo self, ExtensionMethodInfo other) {
1909 return self.Equals(other);
1912 public static bool operator !=(ExtensionMethodInfo self, ExtensionMethodInfo other) {
1913 return !self.Equals(other);
1916 public override int GetHashCode() {
1917 return _method.GetHashCode();
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.
1924 public bool IsExtensionOf(Type/*!*/ type) {
1925 ContractUtils.RequiresNotNull(type, "type");
1926 #if FEATURE_TYPE_EQUIVALENCE
1927 if (type.IsEquivalentTo(ExtendedType)) {
1931 if (type == _extendedType) {
1935 if (!_extendedType.GetTypeInfo().ContainsGenericParameters) {
1940 // Ignores constraints that can't be instantiated given the information we have (type of the first parameter).
1943 // void Foo<S, T>(this S x, T y) where S : T;
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.
1948 return ReflectionUtils.BindGenericParameters(_extendedType, type, true) != null;