From b28d334f0ad181876af4ef4dc090630d76eca135 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 14 Jun 2019 21:34:05 +0200 Subject: [PATCH] [System.Private.CoreLib] Extract RuntimeType for easier refactoring Commit migrated from https://github.com/mono/mono/commit/b5b58d67cf6fd4f5431ae2b6c3e3fc4ec71f91b3 --- .../System.Private.CoreLib.csproj | 1 - .../src/System/RuntimeType.cs | 2204 +++++++++++++++++++- 2 files changed, 2141 insertions(+), 64 deletions(-) diff --git a/src/mono/netcore/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/netcore/System.Private.CoreLib/System.Private.CoreLib.csproj index 33f069a..1489629 100644 --- a/src/mono/netcore/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/netcore/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -290,7 +290,6 @@ - diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.cs b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.cs index f89f2f1..ef3f9d9 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.cs @@ -8,8 +8,8 @@ using System.Threading; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Globalization; -using System.Security; -using System.Runtime.Serialization; +using System.Diagnostics; +using CustomAttribute=System.MonoCustomAttrs; namespace System { @@ -24,13 +24,113 @@ namespace System } [StructLayout (LayoutKind.Sequential)] - partial class RuntimeType + sealed partial class RuntimeType : TypeInfo, ICloneable { + internal enum MemberListType + { + All, + CaseSensitive, + CaseInsensitive, + HandleToInfo + } + + // Helper to build lists of MemberInfos. Special cased to avoid allocations for lists of one element. + private struct ListBuilder where T : class + { + T[] _items; + T _item; + int _count; + int _capacity; + + public ListBuilder(int capacity) + { + _items = null; + _item = null; + _count = 0; + _capacity = capacity; + } + + public T this[int index] + { + get + { + return (_items != null) ? _items[index] : _item; + } + } + + public T[] ToArray() + { + if (_count == 0) + return Array.Empty (); + if (_count == 1) + return new T[1] { _item }; + + Array.Resize(ref _items, _count); + _capacity = _count; + return _items; + } + + public void CopyTo(Object[] array, int index) + { + if (_count == 0) + return; + + if (_count == 1) + { + array[index] = _item; + return; + } + + Array.Copy(_items, 0, array, index, _count); + } + + public int Count + { + get + { + return _count; + } + } + + public void Add(T item) + { + if (_count == 0) + { + _item = item; + } + else + { + if (_count == 1) + { + if (_capacity < 2) + _capacity = 4; + _items = new T[_capacity]; + _items[0] = _item; + } + else + if (_capacity == _count) + { + int newCapacity = 2 * _capacity; + Array.Resize(ref _items, newCapacity); + _capacity = newCapacity; + } + + _items[_count] = item; + } + _count++; + } + } + #region keep in sync with object-internals.h [NonSerialized] MonoTypeInfo type_info; #endregion + internal static readonly RuntimeType ValueType = (RuntimeType)typeof(System.ValueType); + + private static readonly RuntimeType ObjectType = (RuntimeType)typeof(System.Object); + private static readonly RuntimeType StringType = (RuntimeType)typeof(System.String); + internal Object GenericCache; internal RuntimeType (Object obj) @@ -95,23 +195,6 @@ namespace System return att.Length != 0 ? ((DefaultMemberAttribute) att [0]).MemberName : null; } - RuntimeConstructorInfo m_serializationCtor; - internal RuntimeConstructorInfo GetSerializationCtor() - { - if (m_serializationCtor == null) { - var s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) }; - - m_serializationCtor = GetConstructor( - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, - CallingConventions.Any, - s_SICtorParamTypes, - null) as RuntimeConstructorInfo; - } - - return m_serializationCtor; - } - internal Object CreateInstanceSlow(bool publicOnly, bool wrapExceptions, bool skipCheckThis, bool fillCache) { //bool bNeedSecurityCheck = true; @@ -137,7 +220,7 @@ namespace System if (ctor == null) { Type elementType = this.GetRootElementType(); if (ReferenceEquals (elementType, typeof (TypedReference)) || ReferenceEquals (elementType, typeof (RuntimeArgumentHandle))) - throw new NotSupportedException (Environment.GetResourceString ("NotSupported_ContainsStackPtr")); + throw new NotSupportedException (("NotSupported_ContainsStackPtr")); if (IsValueType) return CreateInstanceInternal (this); @@ -153,6 +236,13 @@ namespace System return ctor.InternalInvoke (null, null, wrapExceptions); } + private const BindingFlags MemberBindingMask = (BindingFlags)0x000000FF; + private const BindingFlags InvocationMask = (BindingFlags)0x0000FF00; + private const BindingFlags BinderNonCreateInstance = BindingFlags.InvokeMethod | BinderGetSetField | BinderGetSetProperty; + private const BindingFlags BinderGetSetProperty = BindingFlags.GetProperty | BindingFlags.SetProperty; + private const BindingFlags BinderGetSetField = BindingFlags.GetField | BindingFlags.SetField; + private const BindingFlags BinderNonFieldGetSet = (BindingFlags)0x00FFF300; + internal Object CheckValue (Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) { bool failed = false; @@ -161,12 +251,12 @@ namespace System return res; if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding) - throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this)); + throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, ("Arg_ObjObjEx"), value.GetType(), this)); if (binder != null && binder != Type.DefaultBinder) return binder.ChangeType (value, this, culture); - throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this)); + throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, ("Arg_ObjObjEx"), value.GetType(), this)); } object TryConvertToType (object value, ref bool failed) @@ -409,6 +499,71 @@ namespace System } } + internal bool IsDelegate() + { + return GetBaseType() == typeof(System.MulticastDelegate); + } + + public override bool IsAssignableFrom(System.Reflection.TypeInfo? typeInfo) + { + if(typeInfo==null) return false; + return IsAssignableFrom(typeInfo.AsType()); + } + + public override bool IsAssignableFrom(Type? c) + { + if ((object)c == null) + return false; + + if (Object.ReferenceEquals(c, this)) + return true; + + RuntimeType fromType = c.UnderlyingSystemType as RuntimeType; + + // For runtime type, let the VM decide. + if (fromType != null) + { + // both this and c (or their underlying system types) are runtime types + return RuntimeTypeHandle.CanCastTo(fromType, this); + } + + // Special case for TypeBuilder to be backward-compatible. + if (RuntimeFeature.IsDynamicCodeSupported && c is System.Reflection.Emit.TypeBuilder) + { + // If c is a subclass of this class, then c can be cast to this type. + if (c.IsSubclassOf(this)) + return true; + + if (this.IsInterface) + { + return c.ImplementInterface(this); + } + else if (this.IsGenericParameter) + { + Type[] constraints = GetGenericParameterConstraints(); + for (int i = 0; i < constraints.Length; i++) + if (!constraints[i].IsAssignableFrom(c)) + return false; + + return true; + } + } + + // For anything else we return false. + return false; + } + + protected override bool IsValueTypeImpl() + { + // We need to return true for generic parameters with the ValueType constraint. + // So we cannot use the faster RuntimeTypeHandle.IsValueType because it returns + // false for all generic parameters. + if (this == typeof(ValueType) || this == typeof(Enum)) + return false; + + return IsSubclassOf(typeof(ValueType)); + } + public override bool ContainsGenericParameters { get { if (IsGenericParameter) @@ -430,7 +585,7 @@ namespace System public override Type[] GetGenericParameterConstraints () { if (!IsGenericParameter) - throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter")); + throw new InvalidOperationException(("Arg_NotGenericParameter")); var paramInfo = new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this)); Type[] constraints = paramInfo.Constraints; @@ -504,7 +659,7 @@ namespace System public override InterfaceMapping GetInterfaceMap (Type ifaceType) { if (IsGenericParameter) - throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter")); + throw new InvalidOperationException(("Arg_GenericParameter")); if ((object)ifaceType == null) throw new ArgumentNullException("ifaceType"); @@ -512,7 +667,7 @@ namespace System RuntimeType ifaceRtType = ifaceType as RuntimeType; if (ifaceRtType == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType"); + throw new ArgumentException(("Argument_MustBeRuntimeType"), "ifaceType"); InterfaceMapping res; if (!ifaceType.IsInterface) @@ -736,41 +891,1964 @@ namespace System public override bool IsTypeDefinition => RuntimeTypeHandle.IsTypeDefinition (this); - private const int DEFAULT_PACKING_SIZE = 8; - - internal StructLayoutAttribute GetStructLayoutAttribute () - { - if (IsInterface || HasElementType || IsGenericParameter) - return null; - - int pack = 0, size = 0; - LayoutKind layoutKind = LayoutKind.Auto; - switch (Attributes & TypeAttributes.LayoutMask) - { - case TypeAttributes.ExplicitLayout: layoutKind = LayoutKind.Explicit; break; - case TypeAttributes.AutoLayout: layoutKind = LayoutKind.Auto; break; - case TypeAttributes.SequentialLayout: layoutKind = LayoutKind.Sequential; break; - default: break; - } - - CharSet charSet = CharSet.None; - switch (Attributes & TypeAttributes.StringFormatMask) - { - case TypeAttributes.AnsiClass: charSet = CharSet.Ansi; break; - case TypeAttributes.AutoClass: charSet = CharSet.Auto; break; - case TypeAttributes.UnicodeClass: charSet = CharSet.Unicode; break; - default: break; - } - - GetPacking (out pack, out size); - - // Metadata parameter checking should not have allowed 0 for packing size. - // The runtime later converts a packing size of 0 to 8 so do the same here - // because it's more useful from a user perspective. - if (pack == 0) - pack = DEFAULT_PACKING_SIZE; - - return new StructLayoutAttribute (layoutKind) { Pack = pack, Size = size, CharSet = charSet }; - } - } + private const int DEFAULT_PACKING_SIZE = 8; + + internal StructLayoutAttribute GetStructLayoutAttribute () + { + if (IsInterface || HasElementType || IsGenericParameter) + return null; + + int pack = 0, size = 0; + LayoutKind layoutKind = LayoutKind.Auto; + switch (Attributes & TypeAttributes.LayoutMask) + { + case TypeAttributes.ExplicitLayout: layoutKind = LayoutKind.Explicit; break; + case TypeAttributes.AutoLayout: layoutKind = LayoutKind.Auto; break; + case TypeAttributes.SequentialLayout: layoutKind = LayoutKind.Sequential; break; + default: break; + } + + CharSet charSet = CharSet.None; + switch (Attributes & TypeAttributes.StringFormatMask) + { + case TypeAttributes.AnsiClass: charSet = CharSet.Ansi; break; + case TypeAttributes.AutoClass: charSet = CharSet.Auto; break; + case TypeAttributes.UnicodeClass: charSet = CharSet.Unicode; break; + default: break; + } + + GetPacking (out pack, out size); + + // Metadata parameter checking should not have allowed 0 for packing size. + // The runtime later converts a packing size of 0 to 8 so do the same here + // because it's more useful from a user perspective. + if (pack == 0) + pack = DEFAULT_PACKING_SIZE; + + return new StructLayoutAttribute (layoutKind) { Pack = pack, Size = size, CharSet = charSet }; + } + + protected override bool IsContextfulImpl() + { + return RuntimeTypeHandle.IsContextful(this); + } + + protected override bool IsByRefImpl() + { + return RuntimeTypeHandle.IsByRef(this); + } + + protected override bool IsPrimitiveImpl() + { + return RuntimeTypeHandle.IsPrimitive(this); + } + + protected override bool IsPointerImpl() + { + return RuntimeTypeHandle.IsPointer(this); + } + + protected override bool IsCOMObjectImpl() + { + return RuntimeTypeHandle.IsComObject(this, false); + } + + protected override TypeAttributes GetAttributeFlagsImpl() + { + return RuntimeTypeHandle.GetAttributes(this); + } + + public override Type BaseType + { + get + { + return GetBaseType(); + } + } + + private RuntimeType GetBaseType() + { + if (IsInterface) + return null; + + if (RuntimeTypeHandle.IsGenericVariable(this)) + { + Type[] constraints = GetGenericParameterConstraints(); + + RuntimeType baseType = RuntimeType.ObjectType; + + for (int i = 0; i < constraints.Length; i++) + { + RuntimeType constraint = (RuntimeType)constraints[i]; + + if (constraint.IsInterface) + continue; + + if (constraint.IsGenericParameter) + { + GenericParameterAttributes special; + special = constraint.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; + + if ((special & GenericParameterAttributes.ReferenceTypeConstraint) == 0 && + (special & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0) + continue; + } + + baseType = constraint; + } + + if (baseType == RuntimeType.ObjectType) + { + GenericParameterAttributes special; + special = GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; + if ((special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) + baseType = RuntimeType.ValueType; + } + + return baseType; + } + + return RuntimeTypeHandle.GetBaseType(this); + } + + public override Type UnderlyingSystemType + { + get + { + return this; + } + } + + protected override bool HasElementTypeImpl() + { + return RuntimeTypeHandle.HasElementType(this); + } + + public override GenericParameterAttributes GenericParameterAttributes + { + get + { + if (!IsGenericParameter) + throw new InvalidOperationException(("Arg_NotGenericParameter")); + + return GetGenericParameterAttributes (); + } + } + + public override Module Module + { + get + { + return GetRuntimeModule(); + } + } + + internal RuntimeModule GetRuntimeModule() + { + return RuntimeTypeHandle.GetModule(this); + } + + public override Assembly Assembly + { + get + { + return GetRuntimeAssembly(); + } + } + + internal RuntimeAssembly GetRuntimeAssembly() + { + return RuntimeTypeHandle.GetAssembly(this); + } + + public override RuntimeTypeHandle TypeHandle + { + get + { + return new RuntimeTypeHandle(this); + } + } + + protected override bool IsArrayImpl() + { + return RuntimeTypeHandle.IsArray(this); + } + + public override int GetArrayRank() + { + if (!IsArrayImpl()) + throw new ArgumentException(("Argument_HasToBeArrayClass")); + + return RuntimeTypeHandle.GetArrayRank(this); + } + + public override Type GetElementType() + { + return RuntimeTypeHandle.GetElementType(this); + } + + public override string[] GetEnumNames() + { + if (!IsEnum) + throw new ArgumentException(("Arg_MustBeEnum"), "enumType"); + + String[] ret = Enum.InternalGetNames(this); + + // Make a copy since we can't hand out the same array since users can modify them + String[] retVal = new String[ret.Length]; + + Array.Copy(ret, retVal, ret.Length); + + return retVal; + } + + public override Array GetEnumValues() + { + if (!IsEnum) + throw new ArgumentException(("Arg_MustBeEnum"), "enumType"); + + // Get all of the values + ulong[] values = Enum.InternalGetValues(this); + + // Create a generic Array + Array ret = Array.CreateInstance(this, values.Length); + + for (int i = 0; i < values.Length; i++) + { + Object val = Enum.ToObject(this, values[i]); + ret.SetValue(val, i); + } + + return ret; + } + + public override Type GetEnumUnderlyingType() + { + if (!IsEnum) + throw new ArgumentException(("Arg_MustBeEnum"), "enumType"); + + return Enum.InternalGetUnderlyingType(this); + } + + public override bool IsEnumDefined(object value) + { + if (value == null) + throw new ArgumentNullException("value"); + + // Check if both of them are of the same type + RuntimeType valueType = (RuntimeType)value.GetType(); + + // If the value is an Enum then we need to extract the underlying value from it + if (valueType.IsEnum) + { + if (!valueType.IsEquivalentTo(this)) + throw new ArgumentException(SR.Format("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), this.ToString())); + + valueType = (RuntimeType)valueType.GetEnumUnderlyingType(); + } + + // If a string is passed in + if (valueType == RuntimeType.StringType) + { + // Get all of the Fields, calling GetHashEntry directly to avoid copying + string[] names = Enum.InternalGetNames(this); + if (Array.IndexOf(names, value) >= 0) + return true; + else + return false; + } + + // If an enum or integer value is passed in + if (Type.IsIntegerType(valueType)) + { + RuntimeType underlyingType = Enum.InternalGetUnderlyingType(this); + if (underlyingType != valueType) + throw new ArgumentException(SR.Format("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString())); + + ulong[] ulValues = Enum.InternalGetValues(this); + ulong ulValue = Enum.ToUInt64(value); + + return (Array.BinarySearch(ulValues, ulValue) >= 0); + } + else + { + throw new InvalidOperationException(("InvalidOperation_UnknownEnumType")); + } + } + + public override string GetEnumName(object value) + { + if (value == null) + throw new ArgumentNullException("value"); + + Type valueType = value.GetType(); + + if (!(valueType.IsEnum || IsIntegerType(valueType))) + throw new ArgumentException(("Arg_MustBeEnumBaseTypeOrEnum"), "value"); + + ulong[] ulValues = Enum.InternalGetValues(this); + ulong ulValue = Enum.ToUInt64(value); + int index = Array.BinarySearch(ulValues, ulValue); + + if (index >= 0) + { + string[] names = Enum.InternalGetNames(this); + return names[index]; + } + + return null; + } + + internal RuntimeType[] GetGenericArgumentsInternal() + { + return (RuntimeType[]) GetGenericArgumentsInternal (true); + } + + public override Type[] GetGenericArguments() + { + Type[] types = GetGenericArgumentsInternal (false); + + if (types == null) + types = Array.Empty (); + + return types; + } + + public override Type MakeGenericType(Type[] instantiation) + { + if (instantiation == null) + throw new ArgumentNullException("instantiation"); + + RuntimeType[] instantiationRuntimeType = new RuntimeType[instantiation.Length]; + + if (!IsGenericTypeDefinition) + throw new InvalidOperationException( + SR.Format("Arg_NotGenericTypeDefinition", this)); + + if (GetGenericArguments().Length != instantiation.Length) + throw new ArgumentException(("Argument_GenericArgsCount"), "instantiation"); + + for (int i = 0; i < instantiation.Length; i ++) + { + Type instantiationElem = instantiation[i]; + if (instantiationElem == null) + throw new ArgumentNullException(); + + RuntimeType rtInstantiationElem = instantiationElem as RuntimeType; + + if (rtInstantiationElem == null) + { + if (instantiationElem.IsSignatureType) + return MakeGenericSignatureType (this, instantiation); + Type[] instantiationCopy = new Type[instantiation.Length]; + for (int iCopy = 0; iCopy < instantiation.Length; iCopy++) + instantiationCopy[iCopy] = instantiation[iCopy]; + instantiation = instantiationCopy; + if (!RuntimeFeature.IsDynamicCodeSupported) + throw new PlatformNotSupportedException(); + return MakeTypeBuilderInstantiation(instantiation); + } + + instantiationRuntimeType[i] = rtInstantiationElem; + } + + RuntimeType[] genericParameters = GetGenericArgumentsInternal(); + + SanityCheckGenericArguments(instantiationRuntimeType, genericParameters); + + Type ret = null; + ret = MakeGenericType (this, instantiationRuntimeType); + if (ret == null) + throw new TypeLoadException (); + return ret; + } + + Type MakeTypeBuilderInstantiation(Type[] instantiation) + { + return System.Reflection.Emit.TypeBuilderInstantiation.MakeGenericType(this, instantiation); + } + + internal static void SanityCheckGenericArguments(RuntimeType[] genericArguments, RuntimeType[] genericParamters) + { + if (genericArguments == null) + throw new ArgumentNullException(); + + for(int i = 0; i < genericArguments.Length; i++) + { + if (genericArguments[i] == null) + throw new ArgumentNullException(); + + ThrowIfTypeNeverValidGenericArgument(genericArguments[i]); + } + + if (genericArguments.Length != genericParamters.Length) + throw new ArgumentException( + SR.Format("Argument_NotEnoughGenArguments", genericArguments.Length, genericParamters.Length)); + } + + private static void ThrowIfTypeNeverValidGenericArgument(RuntimeType type) + { + if (type.IsPointer || type.IsByRef || type == typeof(void)) + throw new ArgumentException( + SR.Format("Argument_NeverValidGenericArgument", type.ToString())); + } + + private static void SplitName(string fullname, out string name, out string ns) + { + name = null; + ns = null; + + if (fullname == null) + return; + + // Get namespace + int nsDelimiter = fullname.LastIndexOf(".", StringComparison.Ordinal); + if (nsDelimiter != -1 ) + { + ns = fullname.Substring(0, nsDelimiter); + int nameLength = fullname.Length - ns.Length - 1; + if (nameLength != 0) + name = fullname.Substring(nsDelimiter + 1, nameLength); + else + name = ""; + } + else + { + name = fullname; + } + } + + public override bool IsGenericTypeDefinition + { + get { return RuntimeTypeHandle.IsGenericTypeDefinition(this); } + } + + public override bool IsGenericParameter + { + get { return RuntimeTypeHandle.IsGenericVariable(this); } + } + + public override int GenericParameterPosition + { + get + { + if (!IsGenericParameter) + throw new InvalidOperationException(("Arg_NotGenericParameter")); + + return GetGenericParameterPosition (); + } + } + + public override Type GetGenericTypeDefinition() + { + if (!IsGenericType) + throw new InvalidOperationException(("InvalidOperation_NotGenericType")); + + return RuntimeTypeHandle.GetGenericTypeDefinition(this); + } + + public override bool IsGenericType + { + get { return RuntimeTypeHandle.HasInstantiation(this); } + } + + public override bool IsConstructedGenericType + { + get { return IsGenericType && !IsGenericTypeDefinition; } + } + + public Object Clone() + { + return this; + } + + public override Object[] GetCustomAttributes(bool inherit) + { + return CustomAttribute.GetCustomAttributes(this, inherit); + } + + public override Object[] GetCustomAttributes(Type attributeType, bool inherit) + { + if ((object)attributeType == null) + throw new ArgumentNullException("attributeType"); + + RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; + + if (attributeRuntimeType == null) + throw new ArgumentException(("Arg_MustBeType"),"attributeType"); + + return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + if ((object)attributeType == null) + throw new ArgumentNullException("attributeType"); + + RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; + + if (attributeRuntimeType == null) + throw new ArgumentException(("Arg_MustBeType"),"attributeType"); + + return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit); + } + + public override IList GetCustomAttributesData() + { + return CustomAttributeData.GetCustomAttributesInternal(this); + } + + public override MethodInfo[] GetMethods(BindingFlags bindingAttr) + { + return GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, -1, false).ToArray(); + } + + public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) + { + return GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false).ToArray(); + } + + public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) + { + return GetPropertyCandidates(null, bindingAttr, null, false).ToArray(); + } + + public override EventInfo[] GetEvents(BindingFlags bindingAttr) + { + return GetEventCandidates(null, bindingAttr, false).ToArray(); + } + + public override FieldInfo[] GetFields(BindingFlags bindingAttr) + { + return GetFieldCandidates(null, bindingAttr, false).ToArray(); + } + + public override Type[] GetNestedTypes(BindingFlags bindingAttr) + { + return GetNestedTypeCandidates(null, bindingAttr, false).ToArray(); + } + + public override MemberInfo[] GetMembers(BindingFlags bindingAttr) + { + ListBuilder methods = GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, -1, false); + ListBuilder constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false); + ListBuilder properties = GetPropertyCandidates(null, bindingAttr, null, false); + ListBuilder events = GetEventCandidates(null, bindingAttr, false); + ListBuilder fields = GetFieldCandidates(null, bindingAttr, false); + ListBuilder nestedTypes = GetNestedTypeCandidates(null, bindingAttr, false); + // Interfaces are excluded from the result of GetMembers + + MemberInfo[] members = new MemberInfo[ + methods.Count + + constructors.Count + + properties.Count + + events.Count + + fields.Count + + nestedTypes.Count]; + + int i = 0; + methods.CopyTo(members, i); i += methods.Count; + constructors.CopyTo(members, i); i += constructors.Count; + properties.CopyTo(members, i); i += properties.Count; + events.CopyTo(members, i); i += events.Count; + fields.CopyTo(members, i); i += fields.Count; + nestedTypes.CopyTo(members, i); i += nestedTypes.Count; + + return members; + } + + protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) + { + return GetMethodImpl (name, -1, bindingAttr, binder, callConvention, types, modifiers); + } + + protected override MethodInfo GetMethodImpl(String name, int genericParamCount, + BindingFlags bindingAttr, Binder? binder, CallingConventions callConv, + Type[]? types, ParameterModifier[]? modifiers) + { + ListBuilder candidates = GetMethodCandidates(name, bindingAttr, callConv, types, genericParamCount, false); + if (candidates.Count == 0) + return null; + + if (types == null || types.Length == 0) + { + MethodInfo firstCandidate = candidates[0]; + + if (candidates.Count == 1) + { + return firstCandidate; + } + else if (types == null) + { + for (int j = 1; j < candidates.Count; j++) + { + MethodInfo methodInfo = candidates[j]; + if (!System.DefaultBinder.CompareMethodSig (methodInfo, firstCandidate)) + throw new AmbiguousMatchException(("Arg_AmbiguousMatchException")); + } + + // All the methods have the exact same name and sig so return the most derived one. + return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count) as MethodInfo; + } + } + + if (binder == null) + binder = DefaultBinder; + + return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as MethodInfo; + } + + protected override ConstructorInfo GetConstructorImpl( + BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, + Type[] types, ParameterModifier[]? modifiers) + { + ListBuilder candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false); + + if (candidates.Count == 0) + return null; + + if (types.Length == 0 && candidates.Count == 1) + { + ConstructorInfo firstCandidate = candidates[0]; + + ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy(); + if (parameters == null || parameters.Length == 0) + { + return firstCandidate; + } + } + + if ((bindingAttr & BindingFlags.ExactBinding) != 0) + return System.DefaultBinder.ExactBinding(candidates.ToArray(), types, modifiers) as ConstructorInfo; + + if (binder == null) + binder = DefaultBinder; + + return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as ConstructorInfo; + } + + + protected override PropertyInfo GetPropertyImpl( + String name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers) + { + if (name == null) throw new ArgumentNullException(); + + ListBuilder candidates = GetPropertyCandidates(name, bindingAttr, types, false); + + if (candidates.Count == 0) + return null; + + if (types == null || types.Length == 0) + { + // no arguments + if (candidates.Count == 1) + { + PropertyInfo firstCandidate = candidates[0]; + + if ((object)returnType != null && !returnType.IsEquivalentTo(firstCandidate.PropertyType)) + return null; + + return firstCandidate; + } + else + { + if ((object)returnType == null) + // if we are here we have no args or property type to select over and we have more than one property with that name + throw new AmbiguousMatchException(("Arg_AmbiguousMatchException")); + } + } + + if ((bindingAttr & BindingFlags.ExactBinding) != 0) + return System.DefaultBinder.ExactPropertyBinding(candidates.ToArray(), returnType, types, modifiers); + + if (binder == null) + binder = DefaultBinder; + + return binder.SelectProperty(bindingAttr, candidates.ToArray(), returnType, types, modifiers); + } + + public override EventInfo GetEvent(String name, BindingFlags bindingAttr) + { + if (name == null) throw new ArgumentNullException(); + + bool ignoreCase; + MemberListType listType; + RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType); + + RuntimeEventInfo[] cache = GetEvents_internal (name, bindingAttr, listType, this); + EventInfo match = null; + + bindingAttr ^= BindingFlags.DeclaredOnly; + + for (int i = 0; i < cache.Length; i++) + { + RuntimeEventInfo eventInfo = cache[i]; + if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags) + { + if (match != null) + throw new AmbiguousMatchException(("Arg_AmbiguousMatchException")); + + match = eventInfo; + } + } + + return match; + } + + public override FieldInfo GetField(String name, BindingFlags bindingAttr) + { + if (name == null) throw new ArgumentNullException(); + + bool ignoreCase; + MemberListType listType; + RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType); + + RuntimeFieldInfo[] cache = GetFields_internal (name, bindingAttr, listType, this); + FieldInfo match = null; + + bindingAttr ^= BindingFlags.DeclaredOnly; + bool multipleStaticFieldMatches = false; + + for (int i = 0; i < cache.Length; i++) + { + RuntimeFieldInfo fieldInfo = cache[i]; + if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags) + { + if (match != null) + { + if (Object.ReferenceEquals(fieldInfo.DeclaringType, match.DeclaringType)) + throw new AmbiguousMatchException(("Arg_AmbiguousMatchException")); + + if ((match.DeclaringType.IsInterface == true) && (fieldInfo.DeclaringType.IsInterface == true)) + multipleStaticFieldMatches = true; + } + + if (match == null || fieldInfo.DeclaringType.IsSubclassOf(match.DeclaringType) || match.DeclaringType.IsInterface) + match = fieldInfo; + } + } + + if (multipleStaticFieldMatches && match.DeclaringType.IsInterface) + throw new AmbiguousMatchException(("Arg_AmbiguousMatchException")); + + return match; + } + + public override Type GetInterface(String fullname, bool ignoreCase) + { + if (fullname == null) throw new ArgumentNullException(); + + BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.NonPublic; + + bindingAttr &= ~BindingFlags.Static; + + if (ignoreCase) + bindingAttr |= BindingFlags.IgnoreCase; + + string name, ns; + MemberListType listType; + SplitName(fullname, out name, out ns); + RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType); + + List list = null; + var nameComparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + foreach (RuntimeType t in GetInterfaces ()) { + + if (!String.Equals(t.Name, name, nameComparison)) { + continue; + } + + if (list == null) + list = new List (2); + + list.Add (t); + } + + if (list == null) + return null; + + var cache = list.ToArray (); + RuntimeType match = null; + + for (int i = 0; i < cache.Length; i++) + { + RuntimeType iface = cache[i]; + if (RuntimeType.FilterApplyType(iface, bindingAttr, name, false, ns)) + { + if (match != null) + throw new AmbiguousMatchException(("Arg_AmbiguousMatchException")); + + match = iface; + } + } + + return match; + } + + public override Type GetNestedType(String fullname, BindingFlags bindingAttr) + { + if (fullname == null) throw new ArgumentNullException(); + + bool ignoreCase; + bindingAttr &= ~BindingFlags.Static; + string name, ns; + MemberListType listType; + SplitName(fullname, out name, out ns); + RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType); + RuntimeType[] cache = GetNestedTypes_internal (name, bindingAttr, listType); + RuntimeType match = null; + + for (int i = 0; i < cache.Length; i++) + { + RuntimeType nestedType = cache[i]; + if (RuntimeType.FilterApplyType(nestedType, bindingAttr, name, false, ns)) + { + if (match != null) + throw new AmbiguousMatchException(("Arg_AmbiguousMatchException")); + + match = nestedType; + } + } + + return match; + } + + public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr) + { + if (name == null) throw new ArgumentNullException(); + + ListBuilder methods = new ListBuilder(); + ListBuilder constructors = new ListBuilder(); + ListBuilder properties = new ListBuilder(); + ListBuilder events = new ListBuilder(); + ListBuilder fields = new ListBuilder(); + ListBuilder nestedTypes = new ListBuilder(); + + int totalCount = 0; + + // Methods + if ((type & MemberTypes.Method) != 0) + { + methods = GetMethodCandidates(name, bindingAttr, CallingConventions.Any, null, -1, true); + if (type == MemberTypes.Method) + return methods.ToArray(); + totalCount += methods.Count; + } + + // Constructors + if ((type & MemberTypes.Constructor) != 0) + { + constructors = GetConstructorCandidates(name, bindingAttr, CallingConventions.Any, null, true); + if (type == MemberTypes.Constructor) + return constructors.ToArray(); + totalCount += constructors.Count; + } + + // Properties + if ((type & MemberTypes.Property) != 0) + { + properties = GetPropertyCandidates(name, bindingAttr, null, true); + if (type == MemberTypes.Property) + return properties.ToArray(); + totalCount += properties.Count; + } + + // Events + if ((type & MemberTypes.Event) != 0) + { + events = GetEventCandidates(name, bindingAttr, true); + if (type == MemberTypes.Event) + return events.ToArray(); + totalCount += events.Count; + } + + // Fields + if ((type & MemberTypes.Field) != 0) + { + fields = GetFieldCandidates(name, bindingAttr, true); + if (type == MemberTypes.Field) + return fields.ToArray(); + totalCount += fields.Count; + } + + // NestedTypes + if ((type & (MemberTypes.NestedType | MemberTypes.TypeInfo)) != 0) + { + nestedTypes = GetNestedTypeCandidates(name, bindingAttr, true); + if (type == MemberTypes.NestedType || type == MemberTypes.TypeInfo) + return nestedTypes.ToArray(); + totalCount += nestedTypes.Count; + } + + MemberInfo[] compressMembers = (type == (MemberTypes.Method | MemberTypes.Constructor)) ? + new MethodBase[totalCount] : new MemberInfo[totalCount]; + + int i = 0; + methods.CopyTo(compressMembers, i); i += methods.Count; + constructors.CopyTo(compressMembers, i); i += constructors.Count; + properties.CopyTo(compressMembers, i); i += properties.Count; + events.CopyTo(compressMembers, i); i += events.Count; + fields.CopyTo(compressMembers, i); i += fields.Count; + nestedTypes.CopyTo(compressMembers, i); i += nestedTypes.Count; + + return compressMembers; + } + + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + public override Object InvokeMember( + String name, BindingFlags bindingFlags, Binder? binder, Object? target, + Object?[]? providedArgs, ParameterModifier[]? modifiers, CultureInfo? culture, String[]? namedParams) + { + if (IsGenericParameter) + throw new InvalidOperationException(("Arg_GenericParameter")); + + #region Preconditions + if ((bindingFlags & InvocationMask) == 0) + // "Must specify binding flags describing the invoke operation required." + throw new ArgumentException(("Arg_NoAccessSpec"),"bindingFlags"); + + // Provide a default binding mask if none is provided + if ((bindingFlags & MemberBindingMask) == 0) + { + bindingFlags |= BindingFlags.Instance | BindingFlags.Public; + + if ((bindingFlags & BindingFlags.CreateInstance) == 0) + bindingFlags |= BindingFlags.Static; + } + + // There must not be more named parameters than provided arguments + if (namedParams != null) + { + if (providedArgs != null) + { + if (namedParams.Length > providedArgs.Length) + // "Named parameter array can not be bigger than argument array." + throw new ArgumentException(("Arg_NamedParamTooBig"), "namedParams"); + } + else + { + if (namedParams.Length != 0) + // "Named parameter array can not be bigger than argument array." + throw new ArgumentException(("Arg_NamedParamTooBig"), "namedParams"); + } + } + #endregion + + #region Check that any named paramters are not null + if (namedParams != null && Array.IndexOf(namedParams, null) != -1) + // "Named parameter value must not be null." + throw new ArgumentException(("Arg_NamedParamNull"),"namedParams"); + #endregion + + int argCnt = (providedArgs != null) ? providedArgs.Length : 0; + + #region Get a Binder + if (binder == null) + binder = DefaultBinder; + + #endregion + + #region Delegate to Activator.CreateInstance + if ((bindingFlags & BindingFlags.CreateInstance) != 0) + { + if ((bindingFlags & BindingFlags.CreateInstance) != 0 && (bindingFlags & BinderNonCreateInstance) != 0) + // "Can not specify both CreateInstance and another access type." + throw new ArgumentException(("Arg_CreatInstAccess"),"bindingFlags"); + + return Activator.CreateInstance(this, bindingFlags, binder, providedArgs, culture); + } + #endregion + + // PutDispProperty and\or PutRefDispProperty ==> SetProperty. + if ((bindingFlags & (BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty)) != 0) + bindingFlags |= BindingFlags.SetProperty; + + #region Name + if (name == null) + throw new ArgumentNullException("name"); + + if (name.Length == 0 || name.Equals(@"[DISPID=0]")) + { + name = GetDefaultMemberName(); + + if (name == null) + { + // in InvokeMember we always pretend there is a default member if none is provided and we make it ToString + name = "ToString"; + } + } + #endregion + + #region GetField or SetField + bool IsGetField = (bindingFlags & BindingFlags.GetField) != 0; + bool IsSetField = (bindingFlags & BindingFlags.SetField) != 0; + + if (IsGetField || IsSetField) + { + #region Preconditions + if (IsGetField) + { + if (IsSetField) + // "Can not specify both Get and Set on a field." + throw new ArgumentException(("Arg_FldSetGet"),"bindingFlags"); + + if ((bindingFlags & BindingFlags.SetProperty) != 0) + // "Can not specify both GetField and SetProperty." + throw new ArgumentException(("Arg_FldGetPropSet"),"bindingFlags"); + } + else + { + if (providedArgs == null) + throw new ArgumentNullException("providedArgs"); + + if ((bindingFlags & BindingFlags.GetProperty) != 0) + // "Can not specify both SetField and GetProperty." + throw new ArgumentException(("Arg_FldSetPropGet"),"bindingFlags"); + + if ((bindingFlags & BindingFlags.InvokeMethod) != 0) + // "Can not specify Set on a Field and Invoke on a method." + throw new ArgumentException(("Arg_FldSetInvoke"),"bindingFlags"); + } + #endregion + + #region Lookup Field + FieldInfo selFld = null; + FieldInfo[] flds = GetMember(name, MemberTypes.Field, bindingFlags) as FieldInfo[]; + + if (flds.Length == 1) + { + selFld = flds[0]; + } + else if (flds.Length > 0) + { + selFld = binder.BindToField(bindingFlags, flds, IsGetField ? Empty.Value : providedArgs[0], culture); + } + #endregion + + if (selFld != null) + { + #region Invocation on a field + if (selFld.FieldType.IsArray || Object.ReferenceEquals(selFld.FieldType, typeof(System.Array))) + { + #region Invocation of an array Field + int idxCnt; + + if ((bindingFlags & BindingFlags.GetField) != 0) + { + idxCnt = argCnt; + } + else + { + idxCnt = argCnt - 1; + } + + if (idxCnt > 0) + { + // Verify that all of the index values are ints + int[] idx = new int[idxCnt]; + for (int i=0;i results = null; + + for(int i = 0; i < semiFinalists.Length; i ++) + { + MethodInfo semiFinalist = semiFinalists[i]; + + if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt])) + continue; + + if (finalist == null) + { + finalist = semiFinalist; + } + else + { + if (results == null) + { + results = new List(semiFinalists.Length); + results.Add(finalist); + } + + results.Add(semiFinalist); + } + } + + if (results != null) + { + finalists = new MethodInfo[results.Count]; + results.CopyTo(finalists); + } + #endregion + } + #endregion + + #region BindingFlags.GetProperty or BindingFlags.SetProperty + if (finalist == null && isGetProperty || isSetProperty) + { + #region Lookup Property + PropertyInfo[] semiFinalists = GetMember(name, MemberTypes.Property, bindingFlags) as PropertyInfo[]; + List results = null; + + for(int i = 0; i < semiFinalists.Length; i ++) + { + MethodInfo semiFinalist = null; + + if (isSetProperty) + { + semiFinalist = semiFinalists[i].GetSetMethod(true); + } + else + { + semiFinalist = semiFinalists[i].GetGetMethod(true); + } + + if (semiFinalist == null) + continue; + + if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt])) + continue; + + if (finalist == null) + { + finalist = semiFinalist; + } + else + { + if (results == null) + { + results = new List(semiFinalists.Length); + results.Add(finalist); + } + + results.Add(semiFinalist); + } + } + + if (results != null) + { + finalists = new MethodInfo[results.Count]; + results.CopyTo(finalists); + } + #endregion + } + #endregion + + if (finalist != null) + { + #region Invoke + if (finalists == null && + argCnt == 0 && + finalist.GetParametersNoCopy().Length == 0 && + (bindingFlags & BindingFlags.OptionalParamBinding) == 0) + { + //if (useCache && argCnt == props[0].GetParameters().Length) + // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, props[0]); + + return finalist.Invoke(target, bindingFlags, binder, providedArgs, culture); + } + + if (finalists == null) + finalists = new MethodInfo[] { finalist }; + + if (providedArgs == null) + providedArgs = Array.Empty(); + + Object state = null; + + + MethodBase invokeMethod = null; + + try { invokeMethod = binder.BindToMethod(bindingFlags, finalists, ref providedArgs, modifiers, culture, namedParams, out state); } + catch(MissingMethodException) { } + + if (invokeMethod == null) + throw new MissingMethodException(FullName, name); + + //if (useCache && argCnt == invokeMethod.GetParameters().Length) + // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, invokeMethod); + + Object result = ((MethodInfo)invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture); + + if (state != null) + binder.ReorderArgumentArray(ref providedArgs, state); + + return result; + #endregion + } + + throw new MissingMethodException(FullName, name); + } + + private void CreateInstanceCheckThis() + { + if (ContainsGenericParameters) + throw new ArgumentException( + SR.Format("Acc_CreateGenericEx", this)); + + Type elementType = this.GetRootElementType(); + + if (Object.ReferenceEquals(elementType, typeof(ArgIterator))) + throw new NotSupportedException(("Acc_CreateArgIterator")); + + if (Object.ReferenceEquals(elementType, typeof(void))) + throw new NotSupportedException(("Acc_CreateVoid")); + } + + internal Object CreateInstanceImpl( + BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture + ) + { + CreateInstanceCheckThis(); + + Object server = null; + + try + { + try + { + // Store the activation attributes in thread local storage. + // These attributes are later picked up by specialized + // activation services like remote activation services to + // influence the activation. + + if (args == null) + args = Array.Empty (); + + int argCnt = args.Length; + + // Without a binder we need to do use the default binder... + if (binder == null) + binder = DefaultBinder; + + // deal with the __COMObject case first. It is very special because from a reflection point of view it has no ctors + // so a call to GetMemberCons would fail + bool publicOnly = (bindingAttr & BindingFlags.NonPublic) == 0; + bool wrapExceptions = (bindingAttr & BindingFlags.DoNotWrapExceptions) == 0; + if (argCnt == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0 + && (IsGenericCOMObjectImpl() || IsValueType)) + { + server = CreateInstanceDefaultCtor(publicOnly, false, true, wrapExceptions); + } + else + { + ConstructorInfo[] candidates = GetConstructors(bindingAttr); + List matches = new List(candidates.Length); + + // We cannot use Type.GetTypeArray here because some of the args might be null + Type[] argsType = new Type[argCnt]; + for (int i = 0; i < argCnt; i++) + { + if (args[i] != null) + { + argsType[i] = args[i].GetType(); + } + } + + for(int i = 0; i < candidates.Length; i ++) + { + if (FilterApplyConstructorInfo((RuntimeConstructorInfo)candidates[i], bindingAttr, CallingConventions.Any, argsType)) + matches.Add(candidates[i]); + } + + MethodBase[] cons = new MethodBase[matches.Count]; + matches.CopyTo(cons); + if (cons != null && cons.Length == 0) + cons = null; + + if (cons == null) + { + // Null out activation attributes before throwing exception + throw new MissingMethodException(SR.Format("MissingConstructor_Name", FullName)); + } + + MethodBase invokeMethod; + Object state = null; + + try + { + invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args, null, culture, null, out state); + } + catch (MissingMethodException) { invokeMethod = null; } + + if (invokeMethod == null) + { + throw new MissingMethodException(SR.Format("MissingConstructor_Name", FullName)); + } + + if (invokeMethod.GetParametersNoCopy().Length == 0) + { + if (args.Length != 0) + { + + throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, + ("NotSupported_CallToVarArg"))); + } + + // fast path?? + server = Activator.CreateInstance(this, nonPublic: true, wrapExceptions: wrapExceptions); + } + else + { + server = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture); + + if (state != null) + binder.ReorderArgumentArray(ref args, state); + } + } + } + finally + { + } + } + catch (Exception) + { + throw; + } + + return server; + } + + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + internal Object CreateInstanceDefaultCtor(bool publicOnly, bool skipCheckThis, bool fillCache, bool wrapExceptions + ) + { + if (IsByRefLike) + throw new NotSupportedException (SR.NotSupported_ByRefLike); + + return CreateInstanceSlow(publicOnly, wrapExceptions, skipCheckThis, fillCache); + } + + internal static BindingFlags FilterPreCalculate(bool isPublic, bool isInherited, bool isStatic) + { + BindingFlags bindingFlags = isPublic ? BindingFlags.Public : BindingFlags.NonPublic; + + if (isInherited) + { + // We arrange things so the DeclaredOnly flag means "include inherited members" + bindingFlags |= BindingFlags.DeclaredOnly; + + if (isStatic) + { + bindingFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy; + } + else + { + bindingFlags |= BindingFlags.Instance; + } + } + else + { + if (isStatic) + { + bindingFlags |= BindingFlags.Static; + } + else + { + bindingFlags |= BindingFlags.Instance; + } + } + + return bindingFlags; + } + + // Calculate prefixLookup, ignoreCase, and listType for use by GetXXXCandidates + private static void FilterHelper( + BindingFlags bindingFlags, ref string name, bool allowPrefixLookup, out bool prefixLookup, + out bool ignoreCase, out MemberListType listType) + { + prefixLookup = false; + ignoreCase = false; + + if (name != null) + { + if ((bindingFlags & BindingFlags.IgnoreCase) != 0) + { + name = name.ToLower(CultureInfo.InvariantCulture); + ignoreCase = true; + listType = MemberListType.CaseInsensitive; + } + else + { + listType = MemberListType.CaseSensitive; + } + + if (allowPrefixLookup && name.EndsWith("*", StringComparison.Ordinal)) + { + // We set prefixLookup to true if name ends with a "*". + // We will also set listType to All so that all members are included in + // the candidates which are later filtered by FilterApplyPrefixLookup. + name = name.Substring(0, name.Length - 1); + prefixLookup = true; + listType = MemberListType.All; + } + } + else + { + listType = MemberListType.All; + } + } + + // Used by the singular GetXXX APIs (Event, Field, Interface, NestedType) where prefixLookup is not supported. + private static void FilterHelper(BindingFlags bindingFlags, ref string name, out bool ignoreCase, out MemberListType listType) + { + bool prefixLookup; + FilterHelper(bindingFlags, ref name, false, out prefixLookup, out ignoreCase, out listType); + } + + // Only called by GetXXXCandidates, GetInterfaces, and GetNestedTypes when FilterHelper has set "prefixLookup" to true. + // Most of the plural GetXXX methods allow prefix lookups while the singular GetXXX methods mostly do not. + private static bool FilterApplyPrefixLookup(MemberInfo memberInfo, string name, bool ignoreCase) + { + if (ignoreCase) + { + if (!memberInfo.Name.StartsWith(name, StringComparison.OrdinalIgnoreCase)) + return false; + } + else + { + if (!memberInfo.Name.StartsWith(name, StringComparison.Ordinal)) + return false; + } + + return true; + } + + + // Used by FilterApplyType to perform all the filtering based on name and BindingFlags + private static bool FilterApplyBase( + MemberInfo memberInfo, BindingFlags bindingFlags, bool isPublic, bool isNonProtectedInternal, bool isStatic, + string name, bool prefixLookup) + { + + #region Filter by Public & Private + if (isPublic) + { + if ((bindingFlags & BindingFlags.Public) == 0) + return false; + } + else + { + if ((bindingFlags & BindingFlags.NonPublic) == 0) + return false; + } + #endregion + + bool isInherited = !Object.ReferenceEquals(memberInfo.DeclaringType, memberInfo.ReflectedType); + + #region Filter by DeclaredOnly + if ((bindingFlags & BindingFlags.DeclaredOnly) != 0 && isInherited) + return false; + #endregion + + #region Filter by Static & Instance + if (memberInfo.MemberType != MemberTypes.TypeInfo && + memberInfo.MemberType != MemberTypes.NestedType) + { + if (isStatic) + { + if ((bindingFlags & BindingFlags.FlattenHierarchy) == 0 && isInherited) + return false; + + if ((bindingFlags & BindingFlags.Static) == 0) + return false; + } + else + { + if ((bindingFlags & BindingFlags.Instance) == 0) + return false; + } + } + #endregion + + #region Filter by name wrt prefixLookup and implicitly by case sensitivity + if (prefixLookup == true) + { + if (!FilterApplyPrefixLookup(memberInfo, name, (bindingFlags & BindingFlags.IgnoreCase) != 0)) + return false; + } + #endregion + + #region Asymmetries + // @Asymmetry - Internal, inherited, instance, non-protected, non-virtual, non-abstract members returned + // iff BindingFlags !DeclaredOnly, Instance and Public are present except for fields + if (((bindingFlags & BindingFlags.DeclaredOnly) == 0) && // DeclaredOnly not present + isInherited && // Is inherited Member + + (isNonProtectedInternal) && // Is non-protected internal member + ((bindingFlags & BindingFlags.NonPublic) != 0) && // BindingFlag.NonPublic present + + (!isStatic) && // Is instance member + ((bindingFlags & BindingFlags.Instance) != 0)) // BindingFlag.Instance present + { + MethodInfo methodInfo = memberInfo as MethodInfo; + + if (methodInfo == null) + return false; + + if (!methodInfo.IsVirtual && !methodInfo.IsAbstract) + return false; + } + #endregion + + return true; + } + + + // Used by GetInterface and GetNestedType(s) which don't need parameter type filtering. + private static bool FilterApplyType( + Type type, BindingFlags bindingFlags, string name, bool prefixLookup, string ns) + { + bool isPublic = type.IsNestedPublic || type.IsPublic; + bool isStatic = false; + + if (!RuntimeType.FilterApplyBase(type, bindingFlags, isPublic, type.IsNestedAssembly, isStatic, name, prefixLookup)) + return false; + + if (ns != null && ns != type.Namespace) + return false; + + return true; + } + + + private static bool FilterApplyMethodInfo( + RuntimeMethodInfo method, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes) + { + // Optimization: Pre-Calculate the method binding flags to avoid casting. + return FilterApplyMethodBase(method, method.BindingFlags, bindingFlags, callConv, argumentTypes); + } + + private static bool FilterApplyConstructorInfo( + RuntimeConstructorInfo constructor, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes) + { + // Optimization: Pre-Calculate the method binding flags to avoid casting. + return FilterApplyMethodBase(constructor, constructor.BindingFlags, bindingFlags, callConv, argumentTypes); + } + + // Used by GetMethodCandidates/GetConstructorCandidates, InvokeMember, and CreateInstanceImpl to perform the necessary filtering. + // Should only be called by FilterApplyMethodInfo and FilterApplyConstructorInfo. + private static bool FilterApplyMethodBase( + MethodBase methodBase, BindingFlags methodFlags, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes) + { + bindingFlags ^= BindingFlags.DeclaredOnly; + + #region Check CallingConvention + if ((callConv & CallingConventions.Any) == 0) + { + if ((callConv & CallingConventions.VarArgs) != 0 && + (methodBase.CallingConvention & CallingConventions.VarArgs) == 0) + return false; + + if ((callConv & CallingConventions.Standard) != 0 && + (methodBase.CallingConvention & CallingConventions.Standard) == 0) + return false; + } + #endregion + + #region If argumentTypes supplied + if (argumentTypes != null) + { + ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy(); + + if (argumentTypes.Length != parameterInfos.Length) + { + #region Invoke Member, Get\Set & Create Instance specific case + // If the number of supplied arguments differs than the number in the signature AND + // we are not filtering for a dynamic call -- InvokeMethod or CreateInstance -- filter out the method. + if ((bindingFlags & + (BindingFlags.InvokeMethod | BindingFlags.CreateInstance | BindingFlags.GetProperty | BindingFlags.SetProperty)) == 0) + return false; + + bool testForParamArray = false; + bool excessSuppliedArguments = argumentTypes.Length > parameterInfos.Length; + + if (excessSuppliedArguments) + { // more supplied arguments than parameters, additional arguments could be vararg + #region Varargs + // If method is not vararg, additional arguments can not be passed as vararg + if ((methodBase.CallingConvention & CallingConventions.VarArgs) == 0) + { + testForParamArray = true; + } + else + { + // If Binding flags did not include varargs we would have filtered this vararg method. + // This Invariant established during callConv check. + } + #endregion + } + else + {// fewer supplied arguments than parameters, missing arguments could be optional + #region OptionalParamBinding + if ((bindingFlags & BindingFlags.OptionalParamBinding) == 0) + { + testForParamArray = true; + } + else + { + // From our existing code, our policy here is that if a parameterInfo + // is optional then all subsequent parameterInfos shall be optional. + + // Thus, iff the first parameterInfo is not optional then this MethodInfo is no longer a canidate. + if (!parameterInfos[argumentTypes.Length].IsOptional) + testForParamArray = true; + } + #endregion + } + + #region ParamArray + if (testForParamArray) + { + if (parameterInfos.Length == 0) + return false; + + // The last argument of the signature could be a param array. + bool shortByMoreThanOneSuppliedArgument = argumentTypes.Length < parameterInfos.Length - 1; + + if (shortByMoreThanOneSuppliedArgument) + return false; + + ParameterInfo lastParameter = parameterInfos[parameterInfos.Length - 1]; + + if (!lastParameter.ParameterType.IsArray) + return false; + + if (!lastParameter.IsDefined(typeof(ParamArrayAttribute), false)) + return false; + } + #endregion + + #endregion + } + else + { + #region Exact Binding + if ((bindingFlags & BindingFlags.ExactBinding) != 0) + { + // Legacy behavior is to ignore ExactBinding when InvokeMember is specified. + // Why filter by InvokeMember? If the answer is we leave this to the binder then why not leave + // all the rest of this to the binder too? Further, what other semanitc would the binder + // use for BindingFlags.ExactBinding besides this one? Further, why not include CreateInstance + // in this if statement? That's just InvokeMethod with a constructor, right? + if ((bindingFlags & (BindingFlags.InvokeMethod)) == 0) + { + for(int i = 0; i < parameterInfos.Length; i ++) + { + // a null argument type implies a null arg which is always a perfect match + if ((object)argumentTypes[i] != null && !argumentTypes[i].MatchesParameterTypeExactly(parameterInfos[i])) + return false; + } + } + } + #endregion + } + } + #endregion + + return true; + } + + private ListBuilder GetMethodCandidates( + String name, BindingFlags bindingAttr, CallingConventions callConv, + Type[] types, int genericParamCount, bool allowPrefixLookup) + { + bool prefixLookup, ignoreCase; + MemberListType listType; + RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); + + RuntimeMethodInfo[] cache = GetMethodsByName (name, bindingAttr, listType, this); + ListBuilder candidates = new ListBuilder(cache.Length); + + for (int i = 0; i < cache.Length; i++) + { + RuntimeMethodInfo methodInfo = cache[i]; + if (genericParamCount != -1) { + bool is_generic = methodInfo.IsGenericMethod; + if (genericParamCount == 0 && is_generic) + continue; + else if (genericParamCount > 0 && !is_generic) + continue; + var args = methodInfo.GetGenericArguments (); + if (args.Length != genericParamCount) + continue; + } + if (FilterApplyMethodInfo(methodInfo, bindingAttr, callConv, types) && + (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(methodInfo, name, ignoreCase))) + { + candidates.Add(methodInfo); + } + } + + return candidates; + } + + private ListBuilder GetConstructorCandidates( + string name, BindingFlags bindingAttr, CallingConventions callConv, + Type[] types, bool allowPrefixLookup) + { + bool prefixLookup, ignoreCase; + MemberListType listType; + RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); + + if (!string.IsNullOrEmpty (name) && name != ConstructorInfo.ConstructorName && name != ConstructorInfo.TypeConstructorName) + return new ListBuilder (0); + RuntimeConstructorInfo[] cache = GetConstructors_internal (bindingAttr, this); + ListBuilder candidates = new ListBuilder(cache.Length); + for (int i = 0; i < cache.Length; i++) + { + RuntimeConstructorInfo constructorInfo = cache[i]; + if (FilterApplyConstructorInfo(constructorInfo, bindingAttr, callConv, types) && + (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(constructorInfo, name, ignoreCase))) + { + candidates.Add(constructorInfo); + } + } + + return candidates; + } + + + private ListBuilder GetPropertyCandidates( + String name, BindingFlags bindingAttr, Type[] types, bool allowPrefixLookup) + { + bool prefixLookup, ignoreCase; + MemberListType listType; + RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); + + RuntimePropertyInfo[] cache = GetPropertiesByName (name, bindingAttr, listType, this); + bindingAttr ^= BindingFlags.DeclaredOnly; + + ListBuilder candidates = new ListBuilder(cache.Length); + for (int i = 0; i < cache.Length; i++) + { + RuntimePropertyInfo propertyInfo = cache[i]; + if ((bindingAttr & propertyInfo.BindingFlags) == propertyInfo.BindingFlags && + (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(propertyInfo, name, ignoreCase)) && + (types == null || (propertyInfo.GetIndexParameters().Length == types.Length))) + { + candidates.Add(propertyInfo); + } + } + + return candidates; + } + + private ListBuilder GetEventCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup) + { + bool prefixLookup, ignoreCase; + MemberListType listType; + RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); + + RuntimeEventInfo[] cache = GetEvents_internal (name, bindingAttr, listType, this); + bindingAttr ^= BindingFlags.DeclaredOnly; + + ListBuilder candidates = new ListBuilder(cache.Length); + for (int i = 0; i < cache.Length; i++) + { + RuntimeEventInfo eventInfo = cache[i]; + if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags && + (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(eventInfo, name, ignoreCase))) + { + candidates.Add(eventInfo); + } + } + + return candidates; + } + + private ListBuilder GetFieldCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup) + { + bool prefixLookup, ignoreCase; + MemberListType listType; + RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); + + RuntimeFieldInfo[] cache = GetFields_internal (name, bindingAttr, listType, this); + bindingAttr ^= BindingFlags.DeclaredOnly; + + ListBuilder candidates = new ListBuilder(cache.Length); + for (int i = 0; i < cache.Length; i++) + { + RuntimeFieldInfo fieldInfo = cache[i]; + if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags && + (!prefixLookup || FilterApplyPrefixLookup(fieldInfo, name, ignoreCase))) + { + candidates.Add(fieldInfo); + } + } + + return candidates; + } + + private ListBuilder GetNestedTypeCandidates(String fullname, BindingFlags bindingAttr, bool allowPrefixLookup) + { + bool prefixLookup, ignoreCase; + bindingAttr &= ~BindingFlags.Static; + string name, ns; + MemberListType listType; + SplitName(fullname, out name, out ns); + RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); + + RuntimeType[] cache = GetNestedTypes_internal (name, bindingAttr, listType); + ListBuilder candidates = new ListBuilder(cache.Length); + for (int i = 0; i < cache.Length; i++) + { + RuntimeType nestedClass = cache[i]; + if (RuntimeType.FilterApplyType(nestedClass, bindingAttr, name, prefixLookup, ns)) + { + candidates.Add(nestedClass); + } + } + + return candidates; + } + + internal static RuntimeType GetType(String typeName, bool throwOnError, bool ignoreCase, bool reflectionOnly, + ref StackCrawlMark stackMark) + { + if (typeName == null) + throw new ArgumentNullException("typeName"); + + return RuntimeTypeHandle.GetTypeByName( + typeName, throwOnError, ignoreCase, reflectionOnly, ref stackMark, false); + } + } + + internal enum TypeNameKind + { + Name, + ToString, + SerializationName, + FullName, + } + + // Keep this in sync with FormatFlags defined in typestring.h + enum TypeNameFormatFlags + { + FormatBasic = 0x00000000, // Not a bitmask, simply the tersest flag settings possible + FormatNamespace = 0x00000001, // Include namespace and/or enclosing class names in type names + FormatFullInst = 0x00000002, // Include namespace and assembly in generic types (regardless of other flag settings) + FormatAssembly = 0x00000004, // Include assembly display name in type names + FormatSignature = 0x00000008, // Include signature in method names + FormatNoVersion = 0x00000010, // Suppress version and culture information in all assembly names + FormatAngleBrackets = 0x00000040, // Whether generic types are C or C[T] + FormatStubInfo = 0x00000080, // Include stub info like {unbox-stub} + FormatGenericParam = 0x00000100, // Use !name and !!name for generic type and method parameters + + // If we want to be able to distinguish between overloads whose parameter types have the same name but come from different assemblies, + // we can add FormatAssembly | FormatNoVersion to FormatSerialization. But we are omitting it because it is not a useful scenario + // and including the assembly name will normally increase the size of the serialized data and also decrease the performance. + FormatSerialization = FormatNamespace | + FormatGenericParam | + FormatFullInst + } } -- 2.7.4