Skip to content

Commit 21fe571

Browse files
COMObject invoke through reflection (#106677)
A regression was introduced by implementing IDynamicInterfaceCastable on __ComObject. This means that the order of checks is now important. Made the order consistent in all places and added a test for this particular case.
1 parent b3481b4 commit 21fe571

File tree

4 files changed

+51
-16
lines changed

4 files changed

+51
-16
lines changed

src/coreclr/vm/methodtable.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,22 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule
481481
MethodTable *pServerMT = (*pServer)->GetMethodTable();
482482
PREFIX_ASSUME(pServerMT != NULL);
483483

484+
#ifdef FEATURE_COMINTEROP
485+
if (pServerMT->IsComObjectType() && !pItfMD->HasMethodInstantiation())
486+
{
487+
// interop needs an exact MethodDesc
488+
pItfMD = MethodDesc::FindOrCreateAssociatedMethodDesc(
489+
pItfMD,
490+
ownerType.GetMethodTable(),
491+
FALSE, // forceBoxedEntryPoint
492+
Instantiation(), // methodInst
493+
FALSE, // allowInstParam
494+
TRUE); // forceRemotableMethod
495+
496+
RETURN(pServerMT->GetMethodDescForComInterfaceMethod(pItfMD, false));
497+
}
498+
#endif // !FEATURE_COMINTEROP
499+
484500
// For IDynamicInterfaceCastable, instead of trying to find method implementation in the real object type
485501
// we call GetInterfaceImplementation on the object and call GetMethodDescForInterfaceMethod
486502
// with whatever type it returns.
@@ -501,22 +517,6 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule
501517
RETURN(implTypeHandle.GetMethodTable()->GetMethodDescForInterfaceMethod(ownerType, pItfMD, TRUE /* throwOnConflict */));
502518
}
503519

504-
#ifdef FEATURE_COMINTEROP
505-
if (pServerMT->IsComObjectType() && !pItfMD->HasMethodInstantiation())
506-
{
507-
// interop needs an exact MethodDesc
508-
pItfMD = MethodDesc::FindOrCreateAssociatedMethodDesc(
509-
pItfMD,
510-
ownerType.GetMethodTable(),
511-
FALSE, // forceBoxedEntryPoint
512-
Instantiation(), // methodInst
513-
FALSE, // allowInstParam
514-
TRUE); // forceRemotableMethod
515-
516-
RETURN(pServerMT->GetMethodDescForComInterfaceMethod(pItfMD, false));
517-
}
518-
#endif // !FEATURE_COMINTEROP
519-
520520
// Handle pure COM+ types.
521521
RETURN (pServerMT->GetMethodDescForInterfaceMethod(ownerType, pItfMD, TRUE /* throwOnConflict */));
522522
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace NetClient
5+
{
6+
using System;
7+
using System.Reflection;
8+
using Xunit;
9+
10+
class CallViaReflectionTests
11+
{
12+
private readonly Server.Contract.Servers.NumericTesting server;
13+
14+
public CallViaReflectionTests()
15+
{
16+
this.server = (Server.Contract.Servers.NumericTesting)new Server.Contract.Servers.NumericTestingClass();
17+
}
18+
19+
public void Run()
20+
{
21+
Console.WriteLine(nameof(CallViaReflectionTests));
22+
this.InvokeInstanceMethod();
23+
}
24+
25+
private void InvokeInstanceMethod()
26+
{
27+
MethodInfo minfo = typeof(Server.Contract.INumericTesting).GetMethod("Add_Int")!;
28+
object[] parameters = new object[2] { 10, 20 };
29+
int sum = (int)minfo.Invoke(this.server, parameters);
30+
Assert.Equal(30, sum);
31+
}
32+
}
33+
}

src/tests/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<ItemGroup>
88
<Compile Include="Program.cs" />
99
<Compile Include="ArrayTests.cs" />
10+
<Compile Include="CallViaReflectionTests.cs" />
1011
<Compile Include="ErrorTests.cs" />
1112
<Compile Include="NumericTests.cs" />
1213
<Compile Include="StringTests.cs" />

src/tests/Interop/COM/NETClients/Primitives/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ private static void RunTests()
4040
new StringTests().Run();
4141
new ErrorTests().Run();
4242
new ColorTests().Run();
43+
new CallViaReflectionTests().Run();
4344
}
4445
}
4546
}

0 commit comments

Comments
 (0)