|
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
Imports System.Reflection
Imports System.Diagnostics
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.VisualBasic.CompilerServices.NewLateBinding
Imports Microsoft.VisualBasic.CompilerServices.OverloadResolution
Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
Imports Microsoft.VisualBasic.CompilerServices.Utils
Imports Microsoft.VisualBasic.CompilerServices.ReflectionExtensions
Imports System.Diagnostics.CodeAnalysis
Namespace Microsoft.VisualBasic.CompilerServices
' The symbol table. This consists of helper functions wrapping Reflection
' (which is the actual "symbol table").
Friend NotInheritable Class Symbols
' Prevent creation.
Private Sub New()
End Sub
Friend Enum UserDefinedOperator As SByte
UNDEF
Narrow
Widen
IsTrue
IsFalse
Negate
[Not]
UnaryPlus
Plus
Minus
Multiply
Divide
Power
IntegralDivide
Concatenate
ShiftLeft
ShiftRight
Modulus
[Or]
[Xor]
[And]
[Like]
Equal
NotEqual
Less
LessEqual
GreaterEqual
Greater
MAX
End Enum
Friend Shared ReadOnly NoArguments As Object() = Array.Empty(Of Object)()
Friend Shared ReadOnly NoArgumentNames As String() = Array.Empty(Of String)()
Friend Shared ReadOnly NoTypeArguments As Type() = Array.Empty(Of Type)()
Friend Shared ReadOnly NoTypeParameters As Type() = Array.Empty(Of Type)()
Friend Shared ReadOnly OperatorCLSNames As String()
Friend Shared ReadOnly OperatorNames As String()
Shared Sub New()
OperatorCLSNames = New String(UserDefinedOperator.MAX - 1) {}
OperatorCLSNames(UserDefinedOperator.Narrow) = "op_Explicit"
OperatorCLSNames(UserDefinedOperator.Widen) = "op_Implicit"
OperatorCLSNames(UserDefinedOperator.IsTrue) = "op_True"
OperatorCLSNames(UserDefinedOperator.IsFalse) = "op_False"
OperatorCLSNames(UserDefinedOperator.Negate) = "op_UnaryNegation"
OperatorCLSNames(UserDefinedOperator.Not) = "op_OnesComplement"
OperatorCLSNames(UserDefinedOperator.UnaryPlus) = "op_UnaryPlus"
OperatorCLSNames(UserDefinedOperator.Plus) = "op_Addition"
OperatorCLSNames(UserDefinedOperator.Minus) = "op_Subtraction"
OperatorCLSNames(UserDefinedOperator.Multiply) = "op_Multiply"
OperatorCLSNames(UserDefinedOperator.Divide) = "op_Division"
OperatorCLSNames(UserDefinedOperator.Power) = "op_Exponent"
OperatorCLSNames(UserDefinedOperator.IntegralDivide) = "op_IntegerDivision"
OperatorCLSNames(UserDefinedOperator.Concatenate) = "op_Concatenate"
OperatorCLSNames(UserDefinedOperator.ShiftLeft) = "op_LeftShift"
OperatorCLSNames(UserDefinedOperator.ShiftRight) = "op_RightShift"
OperatorCLSNames(UserDefinedOperator.Modulus) = "op_Modulus"
OperatorCLSNames(UserDefinedOperator.Or) = "op_BitwiseOr"
OperatorCLSNames(UserDefinedOperator.Xor) = "op_ExclusiveOr"
OperatorCLSNames(UserDefinedOperator.And) = "op_BitwiseAnd"
OperatorCLSNames(UserDefinedOperator.Like) = "op_Like"
OperatorCLSNames(UserDefinedOperator.Equal) = "op_Equality"
OperatorCLSNames(UserDefinedOperator.NotEqual) = "op_Inequality"
OperatorCLSNames(UserDefinedOperator.Less) = "op_LessThan"
OperatorCLSNames(UserDefinedOperator.LessEqual) = "op_LessThanOrEqual"
OperatorCLSNames(UserDefinedOperator.GreaterEqual) = "op_GreaterThanOrEqual"
OperatorCLSNames(UserDefinedOperator.Greater) = "op_GreaterThan"
OperatorNames = New String(UserDefinedOperator.MAX - 1) {}
OperatorNames(UserDefinedOperator.Narrow) = "CType"
OperatorNames(UserDefinedOperator.Widen) = "CType"
OperatorNames(UserDefinedOperator.IsTrue) = "IsTrue"
OperatorNames(UserDefinedOperator.IsFalse) = "IsFalse"
OperatorNames(UserDefinedOperator.Negate) = "-"
OperatorNames(UserDefinedOperator.Not) = "Not"
OperatorNames(UserDefinedOperator.UnaryPlus) = "+"
OperatorNames(UserDefinedOperator.Plus) = "+"
OperatorNames(UserDefinedOperator.Minus) = "-"
OperatorNames(UserDefinedOperator.Multiply) = "*"
OperatorNames(UserDefinedOperator.Divide) = "/"
OperatorNames(UserDefinedOperator.Power) = "^"
OperatorNames(UserDefinedOperator.IntegralDivide) = "\"
OperatorNames(UserDefinedOperator.Concatenate) = "&"
OperatorNames(UserDefinedOperator.ShiftLeft) = "<<"
OperatorNames(UserDefinedOperator.ShiftRight) = ">>"
OperatorNames(UserDefinedOperator.Modulus) = "Mod"
OperatorNames(UserDefinedOperator.Or) = "Or"
OperatorNames(UserDefinedOperator.Xor) = "Xor"
OperatorNames(UserDefinedOperator.And) = "And"
OperatorNames(UserDefinedOperator.Like) = "Like"
OperatorNames(UserDefinedOperator.Equal) = "="
OperatorNames(UserDefinedOperator.NotEqual) = "<>"
OperatorNames(UserDefinedOperator.Less) = "<"
OperatorNames(UserDefinedOperator.LessEqual) = "<="
OperatorNames(UserDefinedOperator.GreaterEqual) = ">="
OperatorNames(UserDefinedOperator.Greater) = ">"
End Sub
Friend Shared Function IsUnaryOperator(ByVal op As UserDefinedOperator) As Boolean
Select Case op
Case UserDefinedOperator.Narrow,
UserDefinedOperator.Widen,
UserDefinedOperator.IsTrue,
UserDefinedOperator.IsFalse,
UserDefinedOperator.Negate,
UserDefinedOperator.Not,
UserDefinedOperator.UnaryPlus
Return True
End Select
Return False
End Function
Friend Shared Function IsBinaryOperator(ByVal op As UserDefinedOperator) As Boolean
Select Case op
Case UserDefinedOperator.Plus,
UserDefinedOperator.Minus,
UserDefinedOperator.Multiply,
UserDefinedOperator.Divide,
UserDefinedOperator.Power,
UserDefinedOperator.IntegralDivide,
UserDefinedOperator.Concatenate,
UserDefinedOperator.ShiftLeft,
UserDefinedOperator.ShiftRight,
UserDefinedOperator.Modulus,
UserDefinedOperator.Or,
UserDefinedOperator.Xor,
UserDefinedOperator.And,
UserDefinedOperator.Like,
UserDefinedOperator.Equal,
UserDefinedOperator.NotEqual,
UserDefinedOperator.Less,
UserDefinedOperator.LessEqual,
UserDefinedOperator.GreaterEqual,
UserDefinedOperator.Greater
Return True
End Select
Return False
End Function
Friend Shared Function IsUserDefinedOperator(ByVal method As MethodBase) As Boolean
Return method.IsSpecialName AndAlso method.Name.StartsWith("op_", StringComparison.Ordinal)
End Function
Friend Shared Function IsNarrowingConversionOperator(ByVal method As MethodBase) As Boolean
Return method.IsSpecialName AndAlso method.Name.Equals(OperatorCLSNames(UserDefinedOperator.Narrow))
End Function
Friend Shared Function MapToUserDefinedOperator(ByVal method As MethodBase) As UserDefinedOperator
Debug.Assert(IsUserDefinedOperator(method), "expected operator here")
For cursor As Integer = UserDefinedOperator.UNDEF + 1 To UserDefinedOperator.MAX - 1
If method.Name.Equals(OperatorCLSNames(cursor)) Then
Dim paramCount As Integer = method.GetParameters.Length
Dim op As UserDefinedOperator = CType(cursor, UserDefinedOperator)
If (paramCount = 1 AndAlso IsUnaryOperator(op)) OrElse
(paramCount = 2 AndAlso IsBinaryOperator(op)) Then
'Match found, so quit loop early.
Return op
End If
End If
Next
Return UserDefinedOperator.UNDEF
End Function
Friend Shared Function GetTypeCode(ByVal type As System.Type) As TypeCode
Return type.GetTypeCode
End Function
Friend Shared Function MapTypeCodeToType(ByVal typeCode As TypeCode) As <DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)> Type
Select Case typeCode
Case TypeCode.Boolean : Return GetType(Boolean)
Case TypeCode.SByte : Return GetType(SByte)
Case TypeCode.Byte : Return GetType(Byte)
Case TypeCode.Int16 : Return GetType(Short)
Case TypeCode.UInt16 : Return GetType(UShort)
Case TypeCode.Int32 : Return GetType(Integer)
Case TypeCode.UInt32 : Return GetType(UInteger)
Case TypeCode.Int64 : Return GetType(Long)
Case TypeCode.UInt64 : Return GetType(ULong)
Case TypeCode.Decimal : Return GetType(Decimal)
Case TypeCode.Single : Return GetType(Single)
Case TypeCode.Double : Return GetType(Double)
Case TypeCode.DateTime : Return GetType(Date)
Case TypeCode.Char : Return GetType(Char)
Case TypeCode.String : Return GetType(String)
Case TypeCode.Object : Return GetType(Object)
Case TypeCode.DBNull : Return GetType(DBNull)
Case TypeCode.Empty
'fall through
End Select
Return Nothing
End Function
Friend Shared Function IsRootObjectType(ByVal type As System.Type) As Boolean
Return type Is GetType(Object)
End Function
Friend Shared Function IsRootEnumType(ByVal type As System.Type) As Boolean
Return type Is GetType(System.Enum)
End Function
Friend Shared Function IsValueType(ByVal type As System.Type) As Boolean
Return type.IsValueType
End Function
Friend Shared Function IsEnum(ByVal type As System.Type) As Boolean
Return type.IsEnum
End Function
Friend Shared Function IsArrayType(ByVal type As System.Type) As Boolean
Return type.IsArray
End Function
Friend Shared Function IsStringType(ByVal type As System.Type) As Boolean
Return type Is GetType(String)
End Function
Friend Shared Function IsCharArrayRankOne(ByVal type As System.Type) As Boolean
Return type Is GetType(Char())
End Function
Friend Shared Function IsIntegralType(ByVal typeCode As TypeCode) As Boolean
Select Case typeCode
Case TypeCode.SByte,
TypeCode.Byte,
TypeCode.Int16,
TypeCode.UInt16,
TypeCode.Int32,
TypeCode.UInt32,
TypeCode.Int64,
TypeCode.UInt64
Return True
Case TypeCode.Empty,
TypeCode.Object,
TypeCode.Boolean,
TypeCode.Decimal,
TypeCode.Single,
TypeCode.Double,
TypeCode.DateTime,
TypeCode.Char,
TypeCode.String
'Fall through to end.
End Select
Return False
End Function
Friend Shared Function IsNumericType(ByVal typeCode As TypeCode) As Boolean
Select Case typeCode
Case TypeCode.SByte,
TypeCode.Byte,
TypeCode.Int16,
TypeCode.UInt16,
TypeCode.Int32,
TypeCode.UInt32,
TypeCode.Int64,
TypeCode.UInt64,
TypeCode.Decimal,
TypeCode.Single,
TypeCode.Double
Return True
Case TypeCode.Empty,
TypeCode.Object,
TypeCode.Boolean,
TypeCode.DateTime,
TypeCode.Char,
TypeCode.String
'Fall through to end.
End Select
Return False
End Function
Friend Shared Function IsNumericType(ByVal type As System.Type) As Boolean
Return IsNumericType(GetTypeCode(type))
End Function
Friend Shared Function IsIntrinsicType(ByVal typeCode As TypeCode) As Boolean
Select Case typeCode
Case TypeCode.Boolean,
TypeCode.SByte,
TypeCode.Byte,
TypeCode.Int16,
TypeCode.UInt16,
TypeCode.Int32,
TypeCode.UInt32,
TypeCode.Int64,
TypeCode.UInt64,
TypeCode.Decimal,
TypeCode.Single,
TypeCode.Double,
TypeCode.DateTime,
TypeCode.Char,
TypeCode.String
Return True
Case TypeCode.Empty,
TypeCode.Object
'Fall through to end.
End Select
Return False
End Function
Friend Shared Function IsIntrinsicType(ByVal type As System.Type) As Boolean
Return IsIntrinsicType(GetTypeCode(type)) AndAlso Not IsEnum(type)
End Function
Friend Shared Function IsClass(ByVal type As System.Type) As Boolean
Return type.IsClass OrElse IsRootEnumType(type)
End Function
Friend Shared Function IsClassOrValueType(ByVal type As System.Type) As Boolean
Return IsValueType(type) OrElse IsClass(type)
End Function
Friend Shared Function IsInterface(ByVal type As System.Type) As Boolean
Return type.IsInterface
End Function
Friend Shared Function IsClassOrInterface(ByVal type As System.Type) As Boolean
Return IsClass(type) OrElse IsInterface(type)
End Function
Friend Shared Function IsReferenceType(ByVal type As System.Type) As Boolean
Return IsClass(type) OrElse IsInterface(type)
End Function
Friend Shared Function IsGenericParameter(ByVal type As System.Type) As Boolean
Return type.IsGenericParameter
End Function
#If LATEBINDING Then
Friend Shared Function IsCollectionInterface(ByVal type As System.Type) As Boolean
If type.IsInterface AndAlso
((type.IsGenericType AndAlso
(type.GetGenericTypeDefinition() Is GetType(System.Collections.Generic.IList(Of )) OrElse
type.GetGenericTypeDefinition() Is GetType(System.Collections.Generic.ICollection(Of )) OrElse
type.GetGenericTypeDefinition() Is GetType(System.Collections.Generic.IEnumerable(Of )) OrElse
type.GetGenericTypeDefinition() Is GetType(System.Collections.Generic.IReadOnlyList(Of )) OrElse
type.GetGenericTypeDefinition() Is GetType(System.Collections.Generic.IReadOnlyCollection(Of )) OrElse
type.GetGenericTypeDefinition() Is GetType(System.Collections.Generic.IDictionary(Of ,)) OrElse
type.GetGenericTypeDefinition() Is GetType(System.Collections.Generic.IReadOnlyDictionary(Of ,)))) OrElse
type Is GetType(System.Collections.IList) OrElse
type Is GetType(System.Collections.ICollection) OrElse
type Is GetType(System.Collections.IEnumerable) OrElse
type Is GetType(System.ComponentModel.INotifyPropertyChanged) OrElse
type Is GetType(System.Collections.Specialized.INotifyCollectionChanged)) Then
Return True
End If
Return False
End Function
#Else
Friend Shared Function IsCollectionInterface(ByVal Type As System.Type) As Boolean
If Type.IsInterface AndAlso
((Type.IsGenericType AndAlso
(Type.GetGenericTypeDefinition() = GetType(System.Collections.Generic.IList(Of )) OrElse
Type.GetGenericTypeDefinition() = GetType(System.Collections.Generic.ICollection(Of )) OrElse
Type.GetGenericTypeDefinition() = GetType(System.Collections.Generic.IEnumerable(Of )) OrElse
Type.GetGenericTypeDefinition() = GetType(System.Collections.Generic.IReadOnlyList(Of )) OrElse
Type.GetGenericTypeDefinition() = GetType(System.Collections.Generic.IReadOnlyCollection(Of )) OrElse
Type.GetGenericTypeDefinition() = GetType(System.Collections.Generic.IDictionary(Of ,)) OrElse
Type.GetGenericTypeDefinition() = GetType(System.Collections.Generic.IReadOnlyDictionary(Of ,)))) OrElse
Type = GetType(System.Collections.IList) OrElse
Type = GetType(System.Collections.ICollection) OrElse
Type = GetType(System.Collections.IEnumerable) OrElse
Type = GetType(System.ComponentModel.INotifyPropertyChanged) OrElse
Type = GetType(System.Collections.Specialized.INotifyCollectionChanged)) Then
Return True
End If
Return False
End Function
#End If
<UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
Justification:="Calls GetInterfaces but only looks for existing interface type by reference equality. Trimmer guarantees that if the interface type is kept it is also kept on all the types which implement it.")>
Friend Shared Function [Implements](ByVal implementor As System.Type, ByVal [interface] As System.Type) As Boolean
Debug.Assert(Not IsInterface(implementor), "interfaces can't implement, so why call this?")
Debug.Assert(IsInterface([interface]), "expected interface, not " & [interface].FullName)
For Each implemented As Type In implementor.GetInterfaces
If implemented Is [interface] Then
Return True
End If
Next
Return False
End Function
<UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
Justification:="Calls GetInterfaces but only looks for existing interface type by reference equality. Trimmer guarantees that if the interface type is kept it is also kept on all the types which implement it.")>
Friend Shared Function IsOrInheritsFrom(ByVal derived As System.Type, ByVal base As System.Type) As Boolean
Debug.Assert((Not derived.IsByRef) AndAlso (Not derived.IsPointer))
Debug.Assert((Not base.IsByRef) AndAlso (Not base.IsPointer))
If derived Is base Then Return True
If derived.IsGenericParameter() Then
If IsClass(base) AndAlso
(CBool(derived.GenericParameterAttributes() And GenericParameterAttributes.NotNullableValueTypeConstraint)) AndAlso
IsOrInheritsFrom(GetType(System.ValueType), base) Then
Return True
End If
For Each typeConstraint As Type In derived.GetGenericParameterConstraints
If IsOrInheritsFrom(typeConstraint, base) Then
Return True
End If
Next
ElseIf IsInterface(derived) Then
If IsInterface(base) Then
For Each baseInterface As Type In derived.GetInterfaces
If baseInterface Is base Then
Return True
End If
Next
End If
ElseIf IsClass(base) AndAlso IsClassOrValueType(derived) Then
Return derived.IsSubclassOf(base)
End If
Return False
End Function
Friend Shared Function IsGeneric(ByVal type As Type) As Boolean
Return type.IsGenericType
End Function
Friend Shared Function IsInstantiatedGeneric(ByVal type As Type) As Boolean
Return type.IsGenericType AndAlso (Not type.IsGenericTypeDefinition)
End Function
Friend Shared Function IsGeneric(ByVal method As MethodBase) As Boolean
Return method.IsGenericMethod
End Function
Friend Shared Function IsGeneric(ByVal member As MemberInfo) As Boolean
'Returns True whether Method is an instantiated or uninstantiated generic method.
Dim method As MethodBase = TryCast(member, MethodBase)
If method Is Nothing Then Return False
Return IsGeneric(method)
End Function
#If DEBUG Then
Friend Shared Function IsInstantiatedGeneric(ByVal Method As MethodBase) As Boolean
Return Method.IsGenericMethod AndAlso (Not Method.IsGenericMethodDefinition)
End Function
#End If
Friend Shared Function IsRawGeneric(ByVal method As MethodBase) As Boolean
Return method.IsGenericMethod AndAlso method.IsGenericMethodDefinition
End Function
Friend Shared Function GetTypeParameters(ByVal member As MemberInfo) As Type()
Dim method As MethodBase = TryCast(member, MethodBase)
If method Is Nothing Then Return NoTypeParameters
Return method.GetGenericArguments
End Function
Friend Shared Function GetTypeArguments(ByVal type As Type) As Type()
Debug.Assert(type.GetGenericTypeDefinition IsNot Nothing, "expected bound generic type")
Return type.GetGenericArguments
End Function
Friend Shared Function GetInterfaceConstraints(<DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)> ByVal genericParameter As Type) As Type()
'Returns the interface constraints for the type parameter.
Debug.Assert(IsGenericParameter(genericParameter), "expected type parameter")
Return System.Linq.Enumerable.ToArray(genericParameter.GetInterfaces)
End Function
Friend Shared Function GetClassConstraint(ByVal genericParameter As Type) As Type
'Returns the class constraint for the type parameter, Nothing if it has
'no class constraint.
Debug.Assert(IsGenericParameter(genericParameter), "expected type parameter")
'Type parameters with no class constraint have System.Object as their base type.
Dim classConstraint As Type = genericParameter.BaseType
If IsRootObjectType(classConstraint) Then Return Nothing
Return classConstraint
End Function
Friend Shared Function IndexIn(ByVal possibleGenericParameter As Type, ByVal genericMethodDef As MethodBase) As Integer
'Returns the index of PossibleGenericParameter in Method. If the generic param cannot be found,
'returns -1
Debug.Assert(genericMethodDef IsNot Nothing AndAlso IsRawGeneric(genericMethodDef), "Uninstantiated generic expected!!!")
If IsGenericParameter(possibleGenericParameter) AndAlso
possibleGenericParameter.DeclaringMethod IsNot Nothing AndAlso
AreGenericMethodDefsEqual(possibleGenericParameter.DeclaringMethod, genericMethodDef) Then
Return possibleGenericParameter.GenericParameterPosition
End If
Return -1
End Function
Friend Shared Function RefersToGenericParameter(ByVal referringType As Type, ByVal method As MethodBase) As Boolean
'Given ReferringType, determine if it contains any usages of the generic parameters of Method.
'For example, the referring types T and C1(Of T) and T() refer to a generic param of Sub F(Of T).
If Not IsRawGeneric(method) Then Return False
If referringType.IsByRef Then referringType = GetElementType(referringType)
If IsGenericParameter(referringType) Then
'Is T a generic parameter of Method?
Debug.Assert(referringType.DeclaringMethod.IsGenericMethodDefinition, "Unexpected generic method instantiation!!!")
If AreGenericMethodDefsEqual(referringType.DeclaringMethod, method) Then
Return True
End If
ElseIf IsGeneric(referringType) Then
'For C1(Of T, U, V), recurse on T, U, and V.
For Each param As Type In GetTypeArguments(referringType)
If RefersToGenericParameter(param, method) Then
Return True
End If
Next
ElseIf IsArrayType(referringType) Then
'For T(), recurse on T.
Return RefersToGenericParameter(referringType.GetElementType, method)
End If
Return False
End Function
'Is T a generic parameter of Type. Note that the clr way of representing type params will
'cause us to return true for the copies of the type params of all the parent types that are
'on the passed in Typ. Note that this clr behavior has been retained because in the run time
'for the uses of this function, this functionality is desired.
'
Friend Shared Function RefersToGenericParameterCLRSemantics(ByVal referringType As Type, ByVal typ As Type) As Boolean
'Given ReferringType, determine if it contains any usages of the generic parameters of Typ.
'For example, the referring types T and C1(Of T) and T() refer to a generic param of Class Cls1(Of T).
If referringType.IsByRef Then referringType = GetElementType(referringType)
If IsGenericParameter(referringType) Then
'Is T a generic parameter of Type. Note that the clr way of representing type params will
'return true for the copies of the type params of all the parent types that are on the
'passed in Typ.
If referringType.DeclaringType Is typ Then
Return True
End If
ElseIf IsGeneric(referringType) Then
'For C1(Of T, U, V), recurse on T, U, and V.
For Each param As Type In GetTypeArguments(referringType)
If RefersToGenericParameterCLRSemantics(param, typ) Then
Return True
End If
Next
ElseIf IsArrayType(referringType) Then
'For T(), recurse on T.
Return RefersToGenericParameterCLRSemantics(referringType.GetElementType, typ)
End If
Return False
End Function
Friend Shared Function AreGenericMethodDefsEqual(ByVal method1 As MethodBase, ByVal method2 As MethodBase) As Boolean
Debug.Assert(method1 IsNot Nothing AndAlso IsRawGeneric(method1), "Generic method def expected!!!")
Debug.Assert(method2 IsNot Nothing AndAlso IsRawGeneric(method2), "Generic method def expected!!!")
' Need to do this kind of comparison because the MethodInfo obtained for a
' base method through type1 is not the same as that obtained from type2
'
Return method1 Is method2 OrElse
method1.HasSameMetadataDefinitionAs(method2)
End Function
Friend Shared Function IsShadows(ByVal method As MethodBase) As Boolean
If method.IsHideBySig Then Return False
If method.IsVirtual AndAlso (method.Attributes And MethodAttributes.NewSlot) = 0 Then
'Only the most derived Overrides member shows up in the member list returned by reflection.
'However, we have to check the most base (Overridable) member because the Shadowing information
'is stored only there.
If (DirectCast(method, MethodInfo).GetRuntimeBaseDefinition().Attributes And MethodAttributes.NewSlot) = 0 Then
Return False
End If
End If
Return True
End Function
Friend Shared Function IsShared(ByVal member As MemberInfo) As Boolean
Select Case member.MemberType
Case MemberTypes.Method
Return DirectCast(member, MethodInfo).IsStatic
Case MemberTypes.Field
Return DirectCast(member, FieldInfo).IsStatic
Case MemberTypes.Constructor
Return DirectCast(member, ConstructorInfo).IsStatic
Case MemberTypes.Property
Return DirectCast(member, PropertyInfo).GetGetMethod.IsStatic
Case Else
Debug.Assert(False, "unexpected membertype")
End Select
Return False
End Function
Friend Shared Function IsParamArray(ByVal parameter As ParameterInfo) As Boolean
Return IsArrayType(parameter.ParameterType) AndAlso parameter.IsDefined(GetType(ParamArrayAttribute), False)
End Function
Friend Shared Function GetElementType(ByVal type As System.Type) As Type
Debug.Assert(type.HasElementType, "expected type with element type")
Return type.GetElementType
End Function
Friend Shared Function AreParametersAndReturnTypesValid(
ByVal parameters As ParameterInfo(),
ByVal returnType As Type) As Boolean
If returnType IsNot Nothing AndAlso (returnType.IsPointer OrElse returnType.IsByRef) Then
Return False
End If
If parameters IsNot Nothing Then
For Each parameter As ParameterInfo In parameters
If parameter.ParameterType.IsPointer Then
Return False
End If
Next
End If
Return True
End Function
Friend Shared Sub GetAllParameterCounts(
ByVal parameters As ParameterInfo(),
ByRef requiredParameterCount As Integer,
ByRef maximumParameterCount As Integer,
ByRef paramArrayIndex As Integer)
Debug.Assert(parameters IsNot Nothing, "expected parameter array")
maximumParameterCount = parameters.Length
'All optional parameters are grouped at the end, so the index of the
'last non-optional (+1) gives us the count of required parameters.
For index As Integer = maximumParameterCount - 1 To 0 Step -1
If Not parameters(index).IsOptional Then
requiredParameterCount = index + 1
Exit For
End If
Next
'Only the last parameter can be a ParamArray, so check it.
If maximumParameterCount <> 0 AndAlso IsParamArray(parameters(maximumParameterCount - 1)) Then
paramArrayIndex = maximumParameterCount - 1
requiredParameterCount -= 1
End If
End Sub
Friend Shared Function IsNonPublicRuntimeMember(ByVal member As MemberInfo) As Boolean
'Disallow latebound calls to internal Microsoft.VisualBasic types
Dim declaringType As System.Type = member.DeclaringType
' For nested types IsNotPublic doesn't return the right value so
' we need to use Not IsPublic.
'
' The following code will only allow calls to members of top level public types
' in the runtime library. Read the reflection documentation and test with
' nested types before changing this code.
Return Not declaringType.IsPublic AndAlso declaringType.Assembly Is Utils.VBRuntimeAssembly
End Function
'this is a utility function, so it doesn't really belong in Symbols, but...
Friend Shared Function HasFlag(ByVal flags As BindingFlags, ByVal flagToTest As BindingFlags) As Boolean
Return CBool(flags And flagToTest)
End Function
Friend NotInheritable Class Container
Private NotInheritable Class InheritanceSorter : Implements IComparer(Of MemberInfo)
Private Sub New()
End Sub
Private Function Compare(ByVal left As MemberInfo, ByVal right As MemberInfo) As Integer Implements IComparer(Of MemberInfo).Compare
Dim leftType As Type = left.DeclaringType
Dim rightType As Type = right.DeclaringType
#If BINDING_LOG Then
'Console.WriteLine("compare: " & LeftType.Name & " " & RightType.Name)
#End If
If leftType Is rightType Then Return 0
If leftType.IsSubclassOf(rightType) Then Return -1
'Necessary to return 1 only for RightType.IsSubclassOf(LeftType)? If no inheritance
'relationhip exists, which is possible when members come from IReflect, returning 1
'is still okay. Returning 1 in this IReflect case will not cause qsort to never terminate.
Return 1
End Function
Friend Shared ReadOnly Instance As InheritanceSorter = New InheritanceSorter
End Class
Private ReadOnly _instance As Object
<DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)>
Private ReadOnly _type As Type
<RequiresUnreferencedCode("Calls Object.GetType() which cannot be statically analyzed")>
Friend Sub New(ByVal instance As Object)
If instance Is Nothing Then
Throw VbMakeObjNotSetException()
End If
_instance = instance
_type = instance.GetType
End Sub
Friend Sub New(
<DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)>
ByVal type As Type)
If type Is Nothing Then
Throw VbMakeObjNotSetException()
End If
_instance = Nothing
_type = type
End Sub
' Try to determine if this object represents a WindowsRuntime object - i.e. it either
' is coming from a WinMD file or is derived from a class coming from a WinMD.
' The logic here matches the CLR's logic of finding a WinRT object.
Friend ReadOnly Property IsWindowsRuntimeObject() As Boolean
Get
Dim curType As Type = _type
While curType IsNot Nothing
If (curType.Attributes And TypeAttributes.WindowsRuntime) = TypeAttributes.WindowsRuntime Then
' Found a WinRT COM object
Return True
ElseIf (curType.Attributes And TypeAttributes.Import) = TypeAttributes.Import Then
' Found a class that is actually imported from COM but not WinRT
' this is definitely a non-WinRT COM object
Return False
End If
curType = curType.BaseType
End While
Return False
End Get
End Property
Friend ReadOnly Property IsCOMObject() As Boolean
Get
Return _type.IsCOMObject
End Get
End Property
Friend ReadOnly Property VBFriendlyName() As String
Get
Return Utils.VBFriendlyName(_type, _instance)
End Get
End Property
Friend ReadOnly Property IsArray() As Boolean
Get
Return IsArrayType(_type) AndAlso _instance IsNot Nothing
End Get
End Property
Friend ReadOnly Property IsValueType() As Boolean
Get
Return Symbols.IsValueType(_type) AndAlso _instance IsNot Nothing
End Get
End Property
Private Const s_defaultLookupFlags As BindingFlags =
BindingFlags.IgnoreCase Or
BindingFlags.FlattenHierarchy Or
BindingFlags.Public Or
BindingFlags.Static Or
BindingFlags.Instance
Private Shared ReadOnly s_noMembers As MemberInfo() = Array.Empty(Of MemberInfo)()
Private Shared Function FilterInvalidMembers(ByVal members As MemberInfo()) As MemberInfo()
If members Is Nothing OrElse members.Length = 0 Then
Return Nothing
End If
Dim validMemberCount As Integer = 0
Dim memberIndex As Integer = 0
For memberIndex = 0 To members.Length - 1
Dim parameters As ParameterInfo() = Nothing
Dim returnType As Type = Nothing
Select Case members(memberIndex).MemberType
Case MemberTypes.Constructor,
MemberTypes.Method
Dim currentMethod As MethodInfo = DirectCast(members(memberIndex), MethodInfo)
parameters = currentMethod.GetParameters
returnType = currentMethod.ReturnType
Case MemberTypes.Property
Dim propertyBlock As PropertyInfo = DirectCast(members(memberIndex), PropertyInfo)
Dim getMethod As MethodInfo = propertyBlock.GetGetMethod
If getMethod IsNot Nothing Then
parameters = getMethod.GetParameters
Else
Dim setMethod As MethodInfo = propertyBlock.GetSetMethod
Dim setParameters As ParameterInfo() = setMethod.GetParameters
parameters = New ParameterInfo(setParameters.Length - 2) {}
System.Array.Copy(setParameters, parameters, parameters.Length)
End If
returnType = propertyBlock.PropertyType
Case MemberTypes.Field
returnType = DirectCast(members(memberIndex), FieldInfo).FieldType
End Select
If AreParametersAndReturnTypesValid(parameters, returnType) Then
validMemberCount += 1
Else
members(memberIndex) = Nothing
End If
Next
If validMemberCount = members.Length Then
Return members
ElseIf validMemberCount > 0 Then
Dim validMembers(validMemberCount - 1) As MemberInfo
Dim validMemberIndex As Integer = 0
For memberIndex = 0 To members.Length - 1
If members(memberIndex) IsNot Nothing Then
validMembers(validMemberIndex) = members(memberIndex)
validMemberIndex += 1
End If
Next
Return validMembers
End If
Return Nothing
End Function
' For a WinRT object, we want to treat members of it's collection interfaces as members of the object
' itself. So GetMembers calls here to find the member in all the collection interfaces that this object
' implements.
<UnconditionalSuppressMessage("ReflectionAnalysis", "IL2065:UnrecognizedReflectionPattern",
Justification:="_type is annotated with .All, so it's Interfaces will be annotated as well and it is safe to call GetMember on the Interfaces.
We should be able to remove once https://github.com/mono/linker/issues/1731 is fixed.")>
Friend Function LookupWinRTCollectionInterfaceMembers(ByVal memberName As String) As List(Of MemberInfo)
Debug.Assert(Me.IsWindowsRuntimeObject(), "Expected a Windows Runtime Object")
Dim result As New List(Of MemberInfo)
For Each implemented As Type In _type.GetInterfaces()
If IsCollectionInterface(implemented) Then
Dim members As MemberInfo() = implemented.GetMember(memberName, s_defaultLookupFlags)
If (members IsNot Nothing) Then
result.AddRange(members)
End If
End If
Next
Return result
End Function
<UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
Justification:="_type is annotated with .All, so it's BaseType will be annotated as well and it is safe to call GetMember on the BaseType.
We should be able to remove once https://github.com/mono/linker/issues/1731 is fixed.")>
Friend Function LookupNamedMembers(ByVal memberName As String) As MemberInfo()
'Returns an array of members matching MemberName sorted by inheritance (most derived first).
'If no members match MemberName, returns an empty array.
Dim result As MemberInfo()
If IsGenericParameter(_type) Then
'Getting the members of a generic parameter follows a special rule.
'In a Latebound context, only members of the class constraint are
'applicable. We will ignore interface constraints. Also, custom
'Reflection can't be involved, so no need to use that.
Dim classConstraint As Type = GetClassConstraint(_type)
If classConstraint IsNot Nothing Then
result = Enumerable.ToArray(classConstraint.GetMember(memberName, s_defaultLookupFlags))
Else
result = Nothing
End If
Else
result = Enumerable.ToArray(_type.GetMember(memberName, s_defaultLookupFlags))
End If
If Me.IsWindowsRuntimeObject() Then
Dim collectionMethods As List(Of MemberInfo) = LookupWinRTCollectionInterfaceMembers(memberName)
If result IsNot Nothing Then
collectionMethods.AddRange(result)
End If
result = collectionMethods.ToArray()
End If
result = FilterInvalidMembers(result)
If result Is Nothing Then
result = s_noMembers
ElseIf result.Length > 1 Then
Array.Sort(Of MemberInfo)(result, InheritanceSorter.Instance)
End If
Return result
End Function
' For a WinRT object, we want to treat members of it's collection interfaces as members of the object
' itself. Search through all the collection interfaces for default members.
<RequiresUnreferencedCode("Calls Container.LookupDefaultMembers")>
Private Function LookupWinRTCollectionDefaultMembers(ByRef defaultMemberName As String) As List(Of MemberInfo)
Debug.Assert(Me.IsWindowsRuntimeObject(), "Expected a Windows Runtime Object")
Dim result As New List(Of MemberInfo)
For Each implemented As Type In _type.GetInterfaces()
If IsCollectionInterface(implemented) Then
Dim members As MemberInfo() = LookupDefaultMembers(defaultMemberName, implemented)
If (members IsNot Nothing) Then
result.AddRange(members)
End If
End If
Next
Return result
End Function
<RequiresUnreferencedCode("Calls Type.GetMember() on a type that cannot be statically analyzed")>
Private Function LookupDefaultMembers(ByRef defaultMemberName As String, ByVal searchType As Type) As MemberInfo()
'Returns an array of default members sorted by inheritance (most derived first).
'If no members match MemberName, returns an empty array.
'The default member name is determined by walking up the inheritance hierarchy looking
'for a DefaultMemberAttribute.
Dim potentialDefaultMemberName As String = Nothing
'Find the default member name.
Dim current As Type = searchType
Do
Dim attributes As Object() = Enumerable.ToArray(current.GetCustomAttributes(GetType(DefaultMemberAttribute), False))
If attributes IsNot Nothing AndAlso attributes.Length > 0 Then
potentialDefaultMemberName = DirectCast(attributes(0), DefaultMemberAttribute).MemberName
Exit Do
End If
current = current.BaseType
Loop While current IsNot Nothing AndAlso Not IsRootObjectType(current)
If potentialDefaultMemberName IsNot Nothing Then
Dim result As MemberInfo() = Enumerable.ToArray(current.GetMember(potentialDefaultMemberName, s_defaultLookupFlags))
result = FilterInvalidMembers(result)
If result IsNot Nothing Then
defaultMemberName = potentialDefaultMemberName
If result.Length > 1 Then
Array.Sort(result, InheritanceSorter.Instance)
End If
Return result
End If
End If
Return s_noMembers
End Function
<RequiresUnreferencedCode("Calls LookupDefaultMembers")>
Friend Function GetMembers(
ByRef memberName As String,
ByVal reportErrors As Boolean) As MemberInfo()
Dim result As MemberInfo()
If memberName Is Nothing Then memberName = ""
If memberName = "" Then
result = Me.LookupDefaultMembers(memberName, _type) 'MemberName is set during this call.
If Me.IsWindowsRuntimeObject() Then
Dim collectionMethods As List(Of MemberInfo) = LookupWinRTCollectionDefaultMembers(memberName)
If result IsNot Nothing Then
collectionMethods.AddRange(result)
End If
result = collectionMethods.ToArray()
End If
If result.Length = 0 Then
If reportErrors Then
Throw New MissingMemberException(
SR.Format(SR.MissingMember_NoDefaultMemberFound1, Me.VBFriendlyName))
End If
Return result
End If
Else
result = Me.LookupNamedMembers(memberName)
If result.Length = 0 Then
If reportErrors Then
Throw New MissingMemberException(
SR.Format(SR.MissingMember_MemberNotFoundOnType2, memberName, Me.VBFriendlyName))
End If
Return result
End If
End If
Return result
End Function
Friend Function GetFieldValue(ByVal field As FieldInfo) As Object
If _instance Is Nothing AndAlso Not IsShared(field) Then
'Reference to non-shared member '|1' requires an object reference.
Throw New NullReferenceException(
SR.Format(SR.NullReference_InstanceReqToAccessMember1, FieldToString(field)))
End If
'
'BEGIN: SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY
'
If IsNonPublicRuntimeMember(field) Then
'No message text intentional - Default BCL message used
Throw New MissingMemberException
End If
'
'END: SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY
'
Return field.GetValue(_instance)
End Function
<RequiresUnreferencedCode("Cannot statically analyze the type of FieldInfo.FieldType")>
Friend Sub SetFieldValue(ByVal field As FieldInfo, ByVal value As Object)
If field.IsInitOnly Then
Throw New MissingMemberException(
SR.Format(SR.MissingMember_ReadOnlyField2, field.Name, Me.VBFriendlyName))
End If
If _instance Is Nothing AndAlso Not IsShared(field) Then
'Reference to non-shared member '|1' requires an object reference.
Throw New NullReferenceException(
SR.Format(SR.NullReference_InstanceReqToAccessMember1, FieldToString(field)))
End If
'
'BEGIN: SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY
'
If IsNonPublicRuntimeMember(field) Then
'No message text intentional - Default BCL message used
Throw New MissingMemberException
End If
'
'END: SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY
'
field.SetValue(_instance, Conversions.ChangeType(value, field.FieldType))
Return
End Sub
<RequiresUnreferencedCode("Calls Conversions.ChangeType")>
Friend Function GetArrayValue(ByVal indices As Object()) As Object
Debug.Assert(Me.IsArray, "expected array when getting array value")
Debug.Assert(indices IsNot Nothing, "expected valid indices")
Dim arrayInstance As Array = DirectCast(_instance, System.Array)
Dim rank As Integer = arrayInstance.Rank
If indices.Length <> rank Then
Throw New RankException
End If
'We use ChangeType to handle potential user-defined conversion operators.
Dim zerothIndex As Integer =
DirectCast(Conversions.ChangeType(indices(0), GetType(Integer)), Integer)
If rank = 1 Then
Return arrayInstance.GetValue(zerothIndex)
Else
Dim firstIndex As Integer =
DirectCast(Conversions.ChangeType(indices(1), GetType(Integer)), Integer)
If rank = 2 Then
Return arrayInstance.GetValue(zerothIndex, firstIndex)
Else
Dim secondIndex As Integer =
DirectCast(Conversions.ChangeType(indices(2), GetType(Integer)), Integer)
If rank = 3 Then
Return arrayInstance.GetValue(zerothIndex, firstIndex, secondIndex)
Else
Dim indexArray As Integer() = New Integer(rank - 1) {}
indexArray(0) = zerothIndex : indexArray(1) = firstIndex : indexArray(2) = secondIndex
For i As Integer = 3 To rank - 1
indexArray(i) =
DirectCast(Conversions.ChangeType(indices(i), GetType(Integer)), Integer)
Next
Return arrayInstance.GetValue(indexArray)
End If
End If
End If
End Function
<RequiresUnreferencedCode("Uses _type.GetElementType which cannot be statically analyzed.")>
Friend Sub SetArrayValue(ByVal arguments As Object())
'The last argument is the Value to be stored into the array. The other arguments are
'the indices into the array.
Debug.Assert(Me.IsArray, "expected array when setting array value")
Debug.Assert(arguments IsNot Nothing, "expected valid indices")
Dim arrayInstance As Array = DirectCast(_instance, System.Array)
Dim rank As Integer = arrayInstance.Rank
If arguments.Length - 1 <> rank Then
Throw New RankException
End If
'To ensure order of evaulation, we must evaluate the Value argument after
'evaluating each index argument.
Dim value As Object = arguments(arguments.Length - 1)
Dim elementType As Type = _type.GetElementType
'We use ChangeType to handle potential user-defined conversion operators.
Dim zerothIndex As Integer =
DirectCast(Conversions.ChangeType(arguments(0), GetType(Integer)), Integer)
If rank = 1 Then
arrayInstance.SetValue(Conversions.ChangeType(value, elementType), zerothIndex)
Return
Else
Dim firstIndex As Integer =
DirectCast(Conversions.ChangeType(arguments(1), GetType(Integer)), Integer)
If rank = 2 Then
arrayInstance.SetValue(Conversions.ChangeType(value, elementType), zerothIndex, firstIndex)
Return
Else
Dim secondIndex As Integer =
DirectCast(Conversions.ChangeType(arguments(2), GetType(Integer)), Integer)
If rank = 3 Then
arrayInstance.SetValue(Conversions.ChangeType(value, elementType), zerothIndex, firstIndex, secondIndex)
Return
Else
Dim indexArray As Integer() = New Integer(rank - 1) {}
indexArray(0) = zerothIndex : indexArray(1) = firstIndex : indexArray(2) = secondIndex
For i As Integer = 3 To rank - 1
indexArray(i) =
DirectCast(Conversions.ChangeType(arguments(i), GetType(Integer)), Integer)
Next
arrayInstance.SetValue(Conversions.ChangeType(value, elementType), indexArray)
Return
End If
End If
End If
End Sub
<RequiresUnreferencedCode("Calls ConstructCallArguments which is unsafe")>
Friend Function InvokeMethod(
ByVal targetProcedure As Method,
ByVal arguments As Object(),
ByVal copyBack As Boolean(),
ByVal flags As BindingFlags) As Object
Dim callTarget As MethodBase = GetCallTarget(targetProcedure, flags)
Debug.Assert(callTarget IsNot Nothing, "must have valid MethodBase")
Debug.Assert(Not targetProcedure.IsGeneric OrElse
DirectCast(targetProcedure.AsMethod, MethodInfo).GetGenericMethodDefinition IsNot Nothing,
"expected bound generic method by this point")
Dim callArguments As Object() =
ConstructCallArguments(targetProcedure, arguments, flags)
If _instance Is Nothing AndAlso Not IsShared(callTarget) Then
'Reference to non-shared member '|1' requires an object reference.
Throw New NullReferenceException(
SR.Format(SR.NullReference_InstanceReqToAccessMember1, targetProcedure.ToString))
End If
'
'BEGIN: SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY
'
If IsNonPublicRuntimeMember(callTarget) Then
'No message text intentional - Default BCL message used
Throw New MissingMemberException
End If
'
'END: SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY SECURITY
'
Dim result As Object
Try
result = callTarget.Invoke(_instance, callArguments)
Catch ex As TargetInvocationException When ex.InnerException IsNot Nothing
'For backwards compatibility, throw the inner exception of a TargetInvocationException.
Throw ex.InnerException
End Try
ReorderArgumentArray(targetProcedure, callArguments, arguments, copyBack, flags)
Return result
End Function
End Class
Friend NotInheritable Class Method
Private _item As MemberInfo 'The underlying method or property reflection object.
Private _rawItem As MethodBase 'The unsubstituted raw generic method.
Private _parameters As ParameterInfo() 'The parameters used for this method by overload resolution.
Private _rawParameters As ParameterInfo() 'The unsubstituted raw parameters of a generic method.
Private _rawParametersFromType As ParameterInfo() 'The unsubstituted raw parameters of a generic method in the raw type.
Private _rawDeclaringType As Type 'The uninstantiated type containing this method.
Friend ReadOnly ParamArrayIndex As Integer 'The index of the ParamArray in the parameters array, -1 if method has no ParamArray.
Friend ReadOnly ParamArrayExpanded As Boolean 'Indicates if this method's ParamArray should be considered in its expanded form.
Friend NotCallable As Boolean 'Indicates if this method has been rejected as uncallable.
Friend RequiresNarrowingConversion As Boolean 'Indicates if an argument requires narrowing one of the method's parameters.
Friend AllNarrowingIsFromObject As Boolean 'Indicates if the type of all arguments which require narrowing to this method's parameters are Object.
Friend LessSpecific As Boolean 'Indicates is this method loses the competition for most specific procedure.
Friend ArgumentsValidated As Boolean 'Indicates if the arguments have been validated against this method.
Friend NamedArgumentMapping As Integer() 'Table of indices into the argument array for mapping named arguments to parameters.
Friend TypeArguments As Type() 'Set of type arguments either supplied or inferred for this method.
Friend ArgumentMatchingDone As Boolean 'Indicates whether the argument matching task (CanMatchArguments) has already been completed for this Method
Private Sub New(
ByVal parameters As ParameterInfo(),
ByVal paramArrayIndex As Integer,
ByVal paramArrayExpanded As Boolean)
Me._parameters = parameters
Me._rawParameters = parameters
Me.ParamArrayIndex = paramArrayIndex
Me.ParamArrayExpanded = paramArrayExpanded
Me.AllNarrowingIsFromObject = True 'Assume True until non-object narrowing is encountered.
End Sub
Friend Sub New(
ByVal method As MethodBase,
ByVal parameters As ParameterInfo(),
ByVal paramArrayIndex As Integer,
ByVal paramArrayExpanded As Boolean)
MyClass.New(parameters, paramArrayIndex, paramArrayExpanded)
Me._item = method
Me._rawItem = method
End Sub
Friend Sub New(
ByVal [property] As PropertyInfo,
ByVal parameters As ParameterInfo(),
ByVal paramArrayIndex As Integer,
ByVal paramArrayExpanded As Boolean)
MyClass.New(parameters, paramArrayIndex, paramArrayExpanded)
Me._item = [property]
End Sub
Friend ReadOnly Property Parameters() As ParameterInfo()
Get
Return _parameters
End Get
End Property
Friend ReadOnly Property RawParameters() As ParameterInfo()
Get
'After a generic method has been bound, we still need access
'to the raw, unbound parameters.
Return _rawParameters
End Get
End Property
Friend ReadOnly Property RawParametersFromType() As ParameterInfo()
<RequiresUnreferencedCode("Cannot statically analyze the type of _item")>
Get
If _rawParametersFromType Is Nothing Then
If Not IsProperty Then
Dim item As MethodInfo = DirectCast(_item, MethodInfo)
If item.IsGenericMethod Then
item = item.GetGenericMethodDefinition()
End If
Dim declaringType As System.Type = item.DeclaringType
If declaringType.IsConstructedGenericType Then
declaringType = declaringType.GetGenericTypeDefinition
End If
Dim rawMethod As MethodInfo = Nothing
For Each candidate As MethodInfo In declaringType.GetTypeInfo.GetDeclaredMethods(item.Name)
If candidate.HasSameMetadataDefinitionAs(item) Then
rawMethod = candidate
Exit For
End If
Next
Debug.Assert(rawMethod IsNot Nothing)
_rawParametersFromType = rawMethod.GetParameters()
Else
_rawParametersFromType = _rawParameters
End If
End If
Return _rawParametersFromType
End Get
End Property
Friend ReadOnly Property DeclaringType() As Type
Get
Return _item.DeclaringType
End Get
End Property
Friend ReadOnly Property RawDeclaringType() As Type
Get
If _rawDeclaringType Is Nothing Then
Dim declaringType As System.Type = _item.DeclaringType
If declaringType.IsConstructedGenericType Then
declaringType = declaringType.GetGenericTypeDefinition
End If
_rawDeclaringType = declaringType
End If
Return _rawDeclaringType
End Get
End Property
Friend ReadOnly Property HasParamArray() As Boolean
Get
Return ParamArrayIndex > -1
End Get
End Property
Friend ReadOnly Property HasByRefParameter() As Boolean
Get
For Each parameter As ParameterInfo In Parameters
If parameter.ParameterType.IsByRef Then
Return True
End If
Next
Return False
End Get
End Property
Friend ReadOnly Property IsProperty() As Boolean
Get
Return _item.MemberType = MemberTypes.Property
End Get
End Property
Friend ReadOnly Property IsMethod() As Boolean
Get
Return _item.MemberType = MemberTypes.Method OrElse
_item.MemberType = MemberTypes.Constructor
End Get
End Property
Friend ReadOnly Property IsGeneric() As Boolean
Get
Return Symbols.IsGeneric(_item)
End Get
End Property
Friend ReadOnly Property TypeParameters() As Type()
Get
Return Symbols.GetTypeParameters(_item)
End Get
End Property
<RequiresUnreferencedCode("Cannot statically infer which method _rawItem is or if it has annotations")>
Friend Function BindGenericArguments() As Boolean
'This function instantiates a generic method with the type arguments supplied or inferred
'for this method.
'
' Constructing the generic binding using Reflection performs
' constraint checking. This is bad if the binding will be used
' to resolve overloaded calls since constraints should not participate
' in the selection process. Instead, constraints should be checked
' after overload resolution has selected a method. For now, there is
' nothing reasonble we can do since Reflection does not allow the
' instantiation of generic methods with arguments that violate the
' constraints. If a violation occurs, catch the exception and return
' false signifying that the binding failed.
Debug.Assert(Me.ArgumentsValidated, "can't bind without validating arguments")
Debug.Assert(Me.IsMethod, "binding to a non-method")
Try
'We use the original raw generic method so we can rebind an already bound Method.
_item = DirectCast(_rawItem, MethodInfo).MakeGenericMethod(TypeArguments)
_parameters = Me.AsMethod.GetParameters
Return True
Catch ex As ArgumentException
Return False
End Try
End Function
Friend Function AsMethod() As MethodBase
Debug.Assert(Me.IsMethod, "casting a non-method to a method")
Return TryCast(_item, MethodBase)
End Function
Friend Function AsProperty() As PropertyInfo
Debug.Assert(Me.IsProperty, "casting a non-property to a property")
Return TryCast(_item, PropertyInfo)
End Function
Public Shared Operator =(ByVal left As Method, ByVal right As Method) As Boolean
Return left._item Is right._item
End Operator
Public Shared Operator <>(ByVal left As Method, ByVal right As Method) As Boolean
Return left._item IsNot right._item
End Operator
Public Shared Operator =(ByVal left As MemberInfo, ByVal right As Method) As Boolean
Return left Is right._item
End Operator
Public Shared Operator <>(ByVal left As MemberInfo, ByVal right As Method) As Boolean
Return left IsNot right._item
End Operator
Public Overrides Function ToString() As String
Return MemberToString(_item)
End Function
#If BINDING_LOG Then
Private Function BoolStr(ByVal x As Boolean) As String
If x Then Return "T" Else Return "F"
End Function
Friend Function DumpContents() As String
Dim result As String = IIf(Me.IsMethod, "Meth", "Prop")
result &= " " & m_Item.Name & " PAExpanded:" & BoolStr(ParamArrayExpanded) & " Container:" & m_Item.DeclaringType.Name & " ("
For Each p As ParameterInfo In Parameters
result &= p.ParameterType.Name & ","
Next
result &= ")"
result &= " PAIndex:" & CStr(ParamArrayIndex)
result &= " NotCallable:" & BoolStr(NotCallable)
result &= " ReqNar:" & BoolStr(RequiresNarrowingConversion)
If RequiresNarrowingConversion Then
result &= " AllNarFromObj:" & BoolStr(AllNarrowingIsFromObject)
End If
Return result
End Function
#End If
End Class
Friend NotInheritable Class TypedNothing
'A class which represents a Nothing reference but with a particular type.
'Normally, a Nothing reference converts to any type. However, during operator
'resolution Nothing should match only one type. This class acts as a place holder
'for Nothing in the argument array and stores the Type which "Nothing" should have.
Friend ReadOnly Type As Type
Friend Sub New(ByVal type As Type)
Me.Type = type
End Sub
End Class
End Class
End Namespace
|