Skip to content

Commit

Permalink
[release/8.0] Add late binding lookup in VB.NET for COM objects (#91433)
Browse files Browse the repository at this point in the history
* Add late binding lookup in VB.NET for COM objects

* Review feedback

* Feedback

---------

Co-authored-by: Aaron R Robinson <arobins@microsoft.com>
  • Loading branch information
github-actions[bot] and AaronRobinsonMSFT authored Sep 6, 2023
1 parent e500806 commit b40f212
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ Namespace Microsoft.VisualBasic.CompilerServices
baseReference = New Container(Instance)
End If

If baseReference.IsCOMObject AndAlso Not baseReference.IsWindowsRuntimeObject Then
Return LateBinding.InternalLateCall(Instance, Type, MemberName, Arguments, ArgumentNames, CopyBack, IgnoreReturn)
End If

Dim idmop As IDynamicMetaObjectProvider = IDOUtils.TryCastToIDMOP(Instance)
If idmop IsNot Nothing AndAlso TypeArguments Is NoTypeArguments Then
Return IDOBinder.IDOCall(idmop, MemberName, Arguments, ArgumentNames, CopyBack, IgnoreReturn)
Expand Down Expand Up @@ -139,7 +143,7 @@ Namespace Microsoft.VisualBasic.CompilerServices
' LateCallInvokeDefault is used to optionally invoke the default action on a call target.
' If the arguments are non-empty, then it isn't optional, and is treated
' as an error if there is no default action.
' Currently we can get here only in the process of execution of NewLateBinding.LateCall.
' Currently we can get here only in the process of execution of NewLateBinding.LateCall.
<System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)>
<DebuggerHiddenAttribute()> <DebuggerStepThroughAttribute()>
<RequiresUnreferencedCode(LateBindingTrimMessage)>
Expand All @@ -155,7 +159,7 @@ Namespace Microsoft.VisualBasic.CompilerServices
' LateGetInvokeDefault is used to optionally invoke the default action.
' If the arguments are non-empty, then it isn't optional, and is treated
' as an error if there is no default action.
' Currently we can get here only in the process of execution of NewLateBinding.LateGet.
' Currently we can get here only in the process of execution of NewLateBinding.LateGet.
<System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)>
<DebuggerHiddenAttribute()> <DebuggerStepThroughAttribute()>
<RequiresUnreferencedCode(LateBindingTrimMessage)>
Expand All @@ -167,7 +171,7 @@ Namespace Microsoft.VisualBasic.CompilerServices

' According to a comment in VBGetBinder.FallbackInvoke, this function is called when
' "The DLR was able to resolve o.member, but not o.member(args)"
' When NewLateBinding.LateGet is evaluating similar expression itself, it never tries to invoke default action
' When NewLateBinding.LateGet is evaluating similar expression itself, it never tries to invoke default action
' if arguments are not empty. It simply returns result of evaluating o.member. I believe, it makes sense
' to follow the same logic here. I.e., if there are no arguments, simply return the instance unless it is an IDO.

Expand Down Expand Up @@ -278,6 +282,9 @@ Namespace Microsoft.VisualBasic.CompilerServices
If argumentNames Is Nothing Then argumentNames = NoArgumentNames

Dim baseReference As Container = New Container(instance)
If baseReference.IsCOMObject AndAlso Not baseReference.IsWindowsRuntimeObject Then
Return LateBinding.LateIndexGet(instance, arguments, argumentNames)
End If

'An r-value expression o(a) has two possible forms:
' 1: o(a) array lookup--where o is an array object and a is a set of indices
Expand Down Expand Up @@ -372,6 +379,10 @@ Namespace Microsoft.VisualBasic.CompilerServices
baseReference = New Container(Instance)
End If

If baseReference.IsCOMObject AndAlso Not baseReference.IsWindowsRuntimeObject Then
Return LateBinding.LateGet(Instance, Type, MemberName, Arguments, ArgumentNames, CopyBack)
End If

Dim invocationFlags As BindingFlags = BindingFlagsInvokeMethod Or BindingFlagsGetProperty

Dim idmop As IDynamicMetaObjectProvider = IDOUtils.TryCastToIDMOP(Instance)
Expand Down Expand Up @@ -653,6 +664,10 @@ Namespace Microsoft.VisualBasic.CompilerServices
End If

Dim methodName As String = ""
If baseReference.IsCOMObject AndAlso Not baseReference.IsWindowsRuntimeObject Then
LateBinding.LateIndexSetComplex(instance, arguments, argumentNames, optimisticSet, rValueBase)
Return
End If

Dim invocationFlags As BindingFlags = BindingFlagsSetProperty

Expand Down Expand Up @@ -927,6 +942,18 @@ Namespace Microsoft.VisualBasic.CompilerServices
baseReference = New Container(Instance)
End If

If baseReference.IsCOMObject AndAlso Not baseReference.IsWindowsRuntimeObject Then
Try
LateBinding.InternalLateSet(Instance, Type, MemberName, Arguments, ArgumentNames, OptimisticSet, CallType)
If RValueBase And Type.IsValueType Then
Throw New Exception(Utils.GetResourceString(SR.RValueBaseForValueType, baseReference.VBFriendlyName, baseReference.VBFriendlyName))
End If
Return
Catch ex As MissingMemberException When OptimisticSet
Return
End Try
End If

Dim invocationFlags As BindingFlags

' If we have a IDO that implements TryGetMember for a property but not TrySetMember then we could land up
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,12 @@ Namespace Microsoft.VisualBasic.CompilerServices
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)
Expand Down

0 comments on commit b40f212

Please sign in to comment.