From 60307a9c0b0bef9630636f2bd77fb869d821ccc1 Mon Sep 17 00:00:00 2001 From: Matho Camara Date: Wed, 27 Sep 2023 16:05:15 +0200 Subject: [PATCH 1/2] Recreate proxy bug of message drivers --- .../Mocks/ResourceWithGenericMethod.cs | 28 +++++++++++++++++++ .../TypeControllerTests.cs | 13 +++++++++ 2 files changed, 41 insertions(+) create mode 100644 src/Tests/Moryx.Resources.Management.Tests/Mocks/ResourceWithGenericMethod.cs diff --git a/src/Tests/Moryx.Resources.Management.Tests/Mocks/ResourceWithGenericMethod.cs b/src/Tests/Moryx.Resources.Management.Tests/Mocks/ResourceWithGenericMethod.cs new file mode 100644 index 000000000..571dca5af --- /dev/null +++ b/src/Tests/Moryx.Resources.Management.Tests/Mocks/ResourceWithGenericMethod.cs @@ -0,0 +1,28 @@ +using Moryx.AbstractionLayer.Drivers; +using Moryx.AbstractionLayer.Drivers.InOut; +using Moryx.AbstractionLayer.Drivers.Message; +using Moryx.AbstractionLayer.Resources; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Moryx.Resources.Management.Tests +{ + public interface IGenericMethodCall : IResource + { + /// + /// Get channel using specialized API + /// + IList GenericMethod(string identifier); + } + + public class ResourceWithGenericMethod : Driver, IGenericMethodCall + { + public IList GenericMethod(string identifier) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Tests/Moryx.Resources.Management.Tests/TypeControllerTests.cs b/src/Tests/Moryx.Resources.Management.Tests/TypeControllerTests.cs index 58fbee6ee..28fb1fbc3 100644 --- a/src/Tests/Moryx.Resources.Management.Tests/TypeControllerTests.cs +++ b/src/Tests/Moryx.Resources.Management.Tests/TypeControllerTests.cs @@ -193,6 +193,19 @@ public void AfterDisposeTheProxyIsDetached() Assert.Throws(() => proxy.MultiplyFoo(2)); } + [Test] + public void ProxyForGenericMethod() + { + // Arrange + var driver = new ResourceWithGenericMethod { Id = 2, Name = "Some other Resource" }; + + // Act + var proxy = (IGenericMethodCall)_typeController.GetProxy(driver); + + // Assert + Assert.IsNotNull(proxy); + } + [Test] public void ReplaceWithProxy() { From dfa8a5798684a808d6eaf941472b749c6899624a Mon Sep 17 00:00:00 2001 From: Thomas Fuchs Date: Fri, 6 Oct 2023 10:49:05 +0200 Subject: [PATCH 2/2] Support generic methods in ProxyBuilder --- .../Resources/ResourceProxyBuilder.cs | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Moryx.Resources.Management/Resources/ResourceProxyBuilder.cs b/src/Moryx.Resources.Management/Resources/ResourceProxyBuilder.cs index c09508ce4..abbcef0f6 100644 --- a/src/Moryx.Resources.Management/Resources/ResourceProxyBuilder.cs +++ b/src/Moryx.Resources.Management/Resources/ResourceProxyBuilder.cs @@ -229,7 +229,33 @@ private static void DefineMethod(TypeBuilder typeBuilder, Type baseType, MethodI var argumentTypes = parameters.Select(p => p.ParameterType).ToArray(); const MethodAttributes methodAttributes = MethodAttributes.Private | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.NewSlot; - var methodBuilder = typeBuilder.DefineMethod(ExplicitMemberName(method), methodAttributes, method.ReturnType, argumentTypes); + MethodBuilder methodBuilder; + if (method.IsGenericMethodDefinition) + { + var genericArguments = method.GetGenericArguments(); + + methodBuilder = typeBuilder.DefineMethod(ExplicitMemberName(method), methodAttributes); + var genericDefinitions = methodBuilder.DefineGenericParameters(genericArguments.Select(ga => ga.Name).ToArray()); + + if (method.ReturnType.IsGenericParameter) + { + methodBuilder.SetReturnType(genericDefinitions[method.ReturnType.GenericParameterPosition]); + } + else if (method.ReturnType.IsGenericType && method.GetGenericArguments()[0].IsGenericParameter) + { + var genericReturn = method.ReturnType.GetGenericTypeDefinition(); + genericReturn = genericReturn.MakeGenericType(genericDefinitions[method.ReturnType.GetGenericArguments()[0].GenericParameterPosition]); + methodBuilder.SetReturnType(genericReturn); + } + else + { + methodBuilder.SetReturnType(method.ReturnType); + } + } + else + { + methodBuilder = typeBuilder.DefineMethod(ExplicitMemberName(method), methodAttributes, method.ReturnType, argumentTypes); + } var isResourceReference = IsResourceReference(method.ReturnType); @@ -265,7 +291,7 @@ private static void DefineMethod(TypeBuilder typeBuilder, Type baseType, MethodI /// Create a unique name for each explicit member implementation /// private static string ExplicitMemberName(MemberInfo member) => $"{member.DeclaringType.Name}_{member.Name}"; - + /// /// Determine if the return type indicates a resource reference