📄 latebinder.vb
字号:
If args.Length > parameters.Length Then Return Nothing 'there are more arguments than parameters End If ReDim preparedArguments(parameters.Length - 1) For i As Integer = 0 To parameters.Length - 1 Dim mappedArgument As Integer = Array.IndexOf(mapping, i) If mappedArgument = -1 Or mappedArgument > args.Length - 1 Then If parameters(i).IsOptional Then preparedArguments(i) = parameters(i).DefaultValue 'initialize optional parameter Else Return Nothing 'not-optional parameter missing End If Else preparedArguments(i) = args(mappedArgument) 'initialize parameter from argument End If Next Return preparedArguments End If ' param array case If IsParamArray(parameters, parameters.Length - 1) Then If args.Length > 0 Then If Not names Is Nothing Then ' for simplicity, care about named prameters case separately For i As Integer = 0 To args.Length - 1 Dim mappedArgument As Integer = Array.IndexOf(mapping, i) If mappedArgument = -1 Then If i = args.Length - 1 Then ' i.e. there is no mapping for param array Exit For ' its ok, just finish preparing arguments End If Else If i = parameters.Length - 1 Then Return Nothing ' param array can not be mapped by name End If preparedArguments(i) = args(mappedArgument) 'initialize parameter from argument End If Next Else If args(args.Length - 1).GetType().IsArray Then If args.Length > parameters.Length Then 'last arg matches param array, but there are too much args Return Nothing End If ' param array passed as array argument Dim index As Integer = args.Length - 1 Dim pcount As Integer = CType(args(args.Length - 1), Array).Length Dim arr As Object = args(index) ReDim Preserve preparedArguments(index + pcount - 1) For i As Integer = 0 To pcount - 1 preparedArguments(index + i) = CType(arr, Array).GetValue(i) Next End If End If End If Return preparedArguments End If For i As Integer = 0 To args.Length - 1 Dim mappedArgument As Integer = Array.IndexOf(mapping, i) If mappedArgument = -1 Or mappedArgument > args.Length - 1 Then Return Nothing 'not-optional parameter missing Else preparedArguments(i) = args(mappedArgument) 'initialize parameter from argument End If Next Return preparedArguments End Function Private Function GetArgumentsMapping(ByVal parameters() As ParameterInfo, ByVal names() As String, ByVal args() As Object) As Integer() Dim mapping(parameters.Length - 1) As Integer For i As Integer = 0 To mapping.Length - 1 mapping(i) = i Next If names Is Nothing Then Return mapping End If Dim parameterNames(parameters.Length - 1) As String For i As Integer = 0 To parameters.Length - 1 parameterNames(i) = parameters(i).Name Next Dim namedArgumentsStart As Integer = args.Length - names.Length For i As Integer = 0 To mapping.Length - 1 If i < names.Length Then Dim m As Integer = Array.IndexOf(parameterNames, names(i)) If m = -1 Then Return Nothing ' mapping failed End If mapping(i + namedArgumentsStart) = m End If Next Return mapping End Function Private Sub PrepareParameters(ByRef args() As Object, ByVal f As MethodBase, ByVal names() As String, ByVal bstate As BState) Dim parameters() As ParameterInfo = f.GetParameters() Dim vals() As Object Dim i As Integer If parameters.Length = 0 Then Return End If vals = PrepareArguments(args, parameters, names, bstate) If parameters.Length <> args.Length Then ReDim args(parameters.Length - 1) ' args must be the same size as parameters End If Dim hasParamArray As Boolean = False For i = 0 To args.Length - 1 ' fit args to parameters until param array If IsParamArray(parameters, i) Then hasParamArray = True Exit For End If args(i) = ConvertValue(vals(i), GetParameterType(parameters, i)) Next If hasParamArray Then ' special case when param array args are passed as one argument that is actually an array If (vals.Length - i) = 1 Then If vals(i).GetType().IsArray Then args(i) = vals(i) Return End If ' if the last value remained is not array, put it in args array as usual End If ' store rest of args (if any) in param array ' if args count is the same as params count excluding param array ' we pass empty param array Dim arrType As Type = GetParameterType(parameters, i) Dim pcount As Integer = vals.Length - i Dim parr As Array = Array.CreateInstance(arrType, pcount) For j As Integer = 0 To pcount - 1 parr.SetValue(ConvertValue(vals(i + j), arrType), j) Next args(parameters.Length - 1) = parr End If End Sub Private Function ConvertValue(ByVal value As Object, ByVal type2 As Type) As Object If value Is Nothing Then Return Nothing End If Dim type1 As Type = value.GetType() If type1 Is type2 Then Return value End If If type1.IsByRef Then type1 = type1.GetElementType() End If If type1.IsPrimitive And type2.IsPrimitive Then Select Case Type.GetTypeCode(type2) Case TypeCode.Boolean Return CBool(value) Case TypeCode.Byte Return CByte(value)#If NET_VER >= 2.0 Then Case TypeCode.SByte Return CSByte(value)#End If Case TypeCode.Char Return CChar(value) Case TypeCode.DateTime Return CDate(value) Case TypeCode.Double Return CDbl(value) Case TypeCode.Decimal Return (CDec(value)) Case TypeCode.Int32 Return CInt(value) Case TypeCode.Int16 Return CShort(value) Case TypeCode.Int64 Return CLng(value)#If NET_VER >= 2.0 Then Case TypeCode.UInt32 Return CUInt(value) Case TypeCode.UInt16 Return CUShort(value) Case TypeCode.UInt64 Return CULng(value)#End If Case TypeCode.Single Return CSng(value) End Select Return Convert.ChangeType(value, type2) Else If type2 Is GetType(String) Then Return CStr(value) End If If type1 Is GetType(String) And type2.IsPrimitive Then Select Case Type.GetTypeCode(type2) Case TypeCode.Boolean Return CBool(value) Case TypeCode.Byte Return CByte(value)#If NET_VER >= 2.0 Then Case TypeCode.SByte Return CSByte(value)#End If Case TypeCode.Char Return CChar(value) Case TypeCode.DateTime Return CDate(value) Case TypeCode.Double Return CDbl(value) Case TypeCode.Decimal Return (CDec(value)) Case TypeCode.Int32 Return CInt(value) Case TypeCode.Int16 Return CShort(value) Case TypeCode.Int64 Return CLng(value)#If NET_VER >= 2.0 Then Case TypeCode.UInt32 Return CUInt(value) Case TypeCode.UInt16 Return CUShort(value) Case TypeCode.UInt64 Return CULng(value)#End If Case TypeCode.Single Return CSng(value) End Select End If End If Return value End Function Private Function CompareMethods(ByVal f1 As MethodBase, ByVal f2 As MethodBase, ByVal args() As Object) As SignatureCompare Dim params1() As ParameterInfo = f1.GetParameters() Dim params2() As ParameterInfo = f2.GetParameters() Dim previous As SignatureCompare = SignatureCompare.Equal Dim current As SignatureCompare Dim paramArrayDecision As Boolean = False For i As Integer = 0 To Math.Max(args.Length, Math.Min(params1.Length, params2.Length)) - 1 'args.Length - 1 Dim f1iType As Type = GetParameterType(params1, i) Dim f2iType As Type = GetParameterType(params2, i) Dim ptype As Type = GetArgumentType(args, i) Dim f1i As TypeConversion = CompareTypes(ptype, f1iType) Dim f2i As TypeConversion = CompareTypes(ptype, f2iType) If f1i = TypeConversion.Widening And f2i = TypeConversion.Widening Then 'current = CompareWideningTypes(f1iType, f2iType, IsParamArray(params1, i), IsParamArray(params2, i)) If Not ptype Is Nothing Then current = CompareWideningTypes(f1iType, f2iType) Else current = CompareWideningTypesWithNothing(f1iType, f2iType) ' for explicit null arguments End If If current = SignatureCompare.Equal Then Dim type1isParamArray As Boolean = IsParamArray(params1, i) Dim type2isParamArray As Boolean = IsParamArray(params2, i) 'If paramArrayDecision Then If previous = SignatureCompare.Equal Or paramArrayDecision Then If type1isParamArray And type2isParamArray Then 'if occurs, it will be always the case until we reach the args end If paramArrayDecision Then current = SignatureCompare.Ambiguity
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -