diff --git a/CHANGELOG.md b/CHANGELOG.md index d4f3c35fd4..df99e12a01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Castle Core Changelog +## Unreleased + +Bugfixes: +- Add missing equality checks in `MethodSignatureComparer.EqualSignatureTypes` to fix `TypeLoadException`s ("Method does not have an implementation") (@stakx, #310) + ## 4.2.0 (2017-09-28) Enhancements: diff --git a/src/Castle.Core.Tests/DynamicProxy.Tests/ExplicitInterfaceTestCase.cs b/src/Castle.Core.Tests/DynamicProxy.Tests/ExplicitInterfaceTestCase.cs index 51a78e0afc..e42dec5dd8 100644 --- a/src/Castle.Core.Tests/DynamicProxy.Tests/ExplicitInterfaceTestCase.cs +++ b/src/Castle.Core.Tests/DynamicProxy.Tests/ExplicitInterfaceTestCase.cs @@ -176,6 +176,13 @@ public void NonVirtualExplicitInterfaceMethods_AreIgnored_OnClassProxy() Assert.AreEqual(5, result); } + + [Test] + public void CreateClassProxy_GivenAdditionalInterfaceWithOverloadedGenericMethodsHavingGenericParameter_SuccessfullyCreatesProxyInstance() + { + var instance = generator.CreateClassProxy(typeof(object), new Type[] { typeof(InterfaceWithOverloadedGenericMethod) }, interceptor); + Assert.NotNull(instance); + } } public class ExplicitInterfaceWithPropertyImplementation : ISimpleInterfaceWithProperty @@ -185,4 +192,18 @@ public int Age get { throw new NotImplementedException(); } } } + + public interface InterfaceWithOverloadedGenericMethod + { + void GenericMethod(GenericClass1 arg); + void GenericMethod(GenericClass2 arg); + } + + public class GenericClass1 + { + } + + public class GenericClass2 + { + } } \ No newline at end of file diff --git a/src/Castle.Core.Tests/MethodComparerTestCase.cs b/src/Castle.Core.Tests/MethodComparerTestCase.cs index 411ae25160..80bd925099 100644 --- a/src/Castle.Core.Tests/MethodComparerTestCase.cs +++ b/src/Castle.Core.Tests/MethodComparerTestCase.cs @@ -355,5 +355,28 @@ public void Compare_inherited_double_nested_return_method() Assert.IsTrue(mc.Equals(typeof(Base).GetMethod("GenericMethod7"), typeof(Inherited).GetMethod("GenericMethod7"))); } + + [Test] + public void Compare_two_method_overloads_with_generic_arg_types() + { + var mc = MethodSignatureComparer.Instance; + var methods = typeof(IHaveOverloadedGenericMethod).GetMethods(); + var firstOverload = methods[0]; + var secondOverload = methods[1]; + + // The overloads must obviously have different signatures, or we could never even have + // compiled this test code successfully. The arguments must have a different type: + Assert.IsFalse(mc.Equals(firstOverload, secondOverload)); + } + + private interface IHaveOverloadedGenericMethod + { + void GenericMethod(GenericClass1 arg); + void GenericMethod(GenericClass2 arg); + } + + private class GenericClass1 { } + + private class GenericClass2 { } } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/MethodSignatureComparer.cs b/src/Castle.Core/DynamicProxy/Generators/MethodSignatureComparer.cs index 1d72fa383e..e39b7f4857 100644 --- a/src/Castle.Core/DynamicProxy/Generators/MethodSignatureComparer.cs +++ b/src/Castle.Core/DynamicProxy/Generators/MethodSignatureComparer.cs @@ -79,20 +79,35 @@ public bool EqualParameters(MethodInfo x, MethodInfo y) public bool EqualSignatureTypes(Type x, Type y) { - if (x.GetTypeInfo().IsGenericParameter != y.GetTypeInfo().IsGenericParameter) + var xti = x.GetTypeInfo(); + var yti = y.GetTypeInfo(); + + if (xti.IsGenericParameter != yti.IsGenericParameter) + { + return false; + } + else if (xti.IsGenericType != yti.IsGenericType) { return false; } - if (x.GetTypeInfo().IsGenericParameter) + if (xti.IsGenericParameter) { - if (x.GetTypeInfo().GenericParameterPosition != y.GetTypeInfo().GenericParameterPosition) + if (xti.GenericParameterPosition != yti.GenericParameterPosition) { return false; } } - else if (x.GetTypeInfo().IsGenericType) + else if (xti.IsGenericType) { + var xGenericTypeDef = xti.GetGenericTypeDefinition(); + var yGenericTypeDef = yti.GetGenericTypeDefinition(); + + if (xGenericTypeDef != yGenericTypeDef) + { + return false; + } + var xArgs = x.GetGenericArguments(); var yArgs = y.GetGenericArguments();