Fix errors when DispatchProxy is not public type (#47903)
authorKrzysztof Wicher <mordotymoja@gmail.com>
Tue, 9 Feb 2021 07:22:36 +0000 (08:22 +0100)
committerGitHub <noreply@github.com>
Tue, 9 Feb 2021 07:22:36 +0000 (08:22 +0100)
* Fix non-public DispatchProxy + tests

* Disable mono tests affected by #47989

src/libraries/System.Reflection.DispatchProxy/src/System/Reflection/DispatchProxyGenerator.cs
src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs
src/libraries/System.Reflection.DispatchProxy/tests/System.Reflection.DispatchProxy.Tests.csproj
src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/InternalsVisibleTo.cs [new file with mode: 0644]
src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/System.Reflection.DispatchProxy.TestDependency.csproj [new file with mode: 0644]
src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/TestTypes.cs [new file with mode: 0644]
src/libraries/System.Reflection.DispatchProxy/tests/TestTypes.cs

index c21a28a..30f20c4 100644 (file)
@@ -252,6 +252,8 @@ namespace System.Reflection
                 _fields.Add(tb.DefineField("_methodInfos", typeof(MethodInfo[]), FieldAttributes.Private));
 
                 _methodInfos = new List<MethodInfo>();
+
+                _assembly.EnsureTypeIsVisible(proxyBaseType);
             }
 
             private void Complete()
index d4a421b..de2fe6a 100644 (file)
@@ -137,6 +137,66 @@ namespace DispatchProxyTests
         }
 
         [Fact]
+        [SkipOnMono("https://github.com/dotnet/runtime/issues/47989")]
+        public static void Create_Using_PrivateProxy()
+        {
+            Assert.NotNull(TestType_PrivateProxy.Proxy<TestType_IHelloService>());
+        }
+
+        [Fact]
+        [SkipOnMono("https://github.com/dotnet/runtime/issues/47989")]
+        public static void Create_Using_PrivateProxyAndInternalService()
+        {
+            Assert.NotNull(TestType_PrivateProxy.Proxy<TestType_InternalInterfaceService>());
+        }
+
+        [Fact]
+        [SkipOnMono("https://github.com/dotnet/runtime/issues/47989")]
+        public static void Create_Using_PrivateProxyAndInternalServiceWithExternalGenericArgument()
+        {
+            Assert.NotNull(TestType_PrivateProxy.Proxy<TestType_InternalInterfaceWithNonPublicExternalGenericArgument>());
+        }
+
+        [Fact]
+        [SkipOnMono("https://github.com/dotnet/runtime/issues/47989")]
+        public static void Create_Using_InternalProxy()
+        {
+            Assert.NotNull(DispatchProxy.Create<TestType_InternalInterfaceService, InternalInvokeProxy>());
+        }
+
+        [Fact]
+        public static void Create_Using_ExternalNonPublicService()
+        {
+            Assert.NotNull(DispatchProxy.Create<DispatchProxyTestDependency.TestType_IExternalNonPublicHiService, TestDispatchProxy>());
+        }
+
+        [Fact]
+        [SkipOnMono("https://github.com/dotnet/runtime/issues/47989")]
+        public static void Create_Using_InternalProxyWithExternalNonPublicBaseType()
+        {
+            Assert.NotNull(DispatchProxy.Create<TestType_IHelloService, TestType_InternalProxyInternalBaseType>());
+        }
+
+        [Fact]
+        public static void Create_Using_InternalServiceImplementingNonPublicExternalService()
+        {
+            Assert.NotNull(DispatchProxy.Create<TestType_InternalInterfaceImplementsNonPublicExternalType, TestDispatchProxy>());
+        }
+
+        [Fact]
+        public static void Create_Using_InternalServiceWithGenericArgumentBeingNonPublicExternalService()
+        {
+            Assert.NotNull(DispatchProxy.Create<TestType_InternalInterfaceWithNonPublicExternalGenericArgument, TestDispatchProxy>());
+        }
+
+        [Fact]
+        [SkipOnMono("https://github.com/dotnet/runtime/issues/47989")]
+        public static void Create_Using_InternalProxyWithBaseTypeImplementingServiceWithgenericArgumentBeingNonPublicExternalService()
+        {
+            Assert.NotNull(DispatchProxy.Create<TestType_IHelloService, TestType_InternalProxyImplementingInterfaceWithGenericArgumentBeingNonPublicExternalType>());
+        }
+
+        [Fact]
         public static void Invoke_Receives_Correct_MethodInfo_And_Arguments()
         {
             bool wasInvoked = false;
index 0b8d674..088e885 100644 (file)
@@ -1,9 +1,16 @@
 <Project Sdk="Microsoft.NET.Sdk">
+  
   <PropertyGroup>
     <TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
   </PropertyGroup>
+
   <ItemGroup>
     <Compile Include="DispatchProxyTests.cs" />
     <Compile Include="TestTypes.cs" />
   </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="TestDependency\System.Reflection.DispatchProxy.TestDependency.csproj" />
+  </ItemGroup>
+  
 </Project>
\ No newline at end of file
diff --git a/src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/InternalsVisibleTo.cs b/src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/InternalsVisibleTo.cs
new file mode 100644 (file)
index 0000000..5126807
--- /dev/null
@@ -0,0 +1,6 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("System.Reflection.DispatchProxy.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")]
diff --git a/src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/System.Reflection.DispatchProxy.TestDependency.csproj b/src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/System.Reflection.DispatchProxy.TestDependency.csproj
new file mode 100644 (file)
index 0000000..9c316ce
--- /dev/null
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Include="InternalsVisibleTo.cs" />
+    <Compile Include="TestTypes.cs" />
+  </ItemGroup>
+
+</Project>
diff --git a/src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/TestTypes.cs b/src/libraries/System.Reflection.DispatchProxy/tests/TestDependency/TestTypes.cs
new file mode 100644 (file)
index 0000000..60d3b8a
--- /dev/null
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Reflection;
+
+namespace DispatchProxyTestDependency
+{
+    internal interface TestType_IExternalNonPublicHiService
+    {
+        string Hi(string message);
+    }
+
+    internal class TestType_ExternalNonPublicBaseClassForProxy : DispatchProxy
+    {
+        protected override object Invoke(MethodInfo targetMethod, object[] args) => null;
+    }
+}
index 5057bda..d4fa174 100644 (file)
@@ -8,6 +8,7 @@ using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Text;
+using DispatchProxyTestDependency;
 
 
 // Test types used to make proxies.
@@ -91,6 +92,20 @@ internal interface TestType_PublicInterfaceService_Implements_Internal : TestTyp
     string Echo2(string message);
 }
 
+internal interface TestType_InternalInterfaceImplementsNonPublicExternalType : TestType_IExternalNonPublicHiService
+{
+    string Hi2(string message);
+}
+
+internal interface TestType_ServiceWithGenericArgument<T>
+{
+    T GetInnerService();
+}
+
+internal interface TestType_InternalInterfaceWithNonPublicExternalGenericArgument : TestType_ServiceWithGenericArgument<TestType_IExternalNonPublicHiService>
+{
+}
+
 public interface TypeType_GenericMethod
 {
     T Echo<T>(T messages);
@@ -111,6 +126,35 @@ public sealed class Sealed_TestDispatchProxy : DispatchProxy
     }
 }
 
+public class TestType_PrivateProxy
+{
+    public static T Proxy<T>() => DispatchProxy.Create<T, InvokeProxy<T>>();
+
+    private class InvokeProxy<T> : DispatchProxy
+    {
+        protected override object Invoke(MethodInfo targetMethod, object[] args) => null;
+    }
+}
+
+internal class TestType_InternalProxyInternalBaseType : TestType_ExternalNonPublicBaseClassForProxy
+{
+}
+
+internal class TestType_InternalProxyImplementingInterfaceWithGenericArgumentBeingNonPublicExternalType : DispatchProxy, TestType_InternalInterfaceWithNonPublicExternalGenericArgument
+{
+    public TestType_IExternalNonPublicHiService GetInnerService() => throw new InvalidOperationException();
+
+    protected override object Invoke(MethodInfo targetMethod, object[] args)
+    {
+        throw new InvalidOperationException();
+    }
+}
+
+internal class InternalInvokeProxy : DispatchProxy
+{
+    protected override object Invoke(MethodInfo targetMethod, object[] args) => null;
+}
+
 // This test double creates a proxy instance for the requested 'ProxyT' type.
 // When methods are invoked on that proxy, it will call a registered callback.
 public class TestDispatchProxy : DispatchProxy