diff --git a/src/NHibernate.Test/DynamicEntity/DataProxyHandler.cs b/src/NHibernate.Test/DynamicEntity/DataProxyHandler.cs index bce91d9424b..69d306147cf 100644 --- a/src/NHibernate.Test/DynamicEntity/DataProxyHandler.cs +++ b/src/NHibernate.Test/DynamicEntity/DataProxyHandler.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Runtime.CompilerServices; using NHibernate.Proxy.DynamicProxy; namespace NHibernate.Test.DynamicEntity @@ -53,6 +54,11 @@ public object Intercept(InvocationInfo info) { return GetHashCode(); } + else if ("Equals".Equals(methodName)) + { + // Redo the base object Equals implementation. + return RuntimeHelpers.Equals(info.Target, info.Arguments[0]); + } return null; } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1881/TestFixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1881/TestFixture.cs new file mode 100644 index 00000000000..96c454cf201 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH1881/TestFixture.cs @@ -0,0 +1,33 @@ +using System; +using System.Linq; +using System.Reflection; +using NHibernate.Collection; +using NHibernate.Collection.Generic; +using NHibernate.Proxy.DynamicProxy; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH1881 +{ + [TestFixture] + [Obsolete] + public class TestFixture + { + [Test] + public void InterfacesShouldBeImplementedExplicitlyOnProxies() + { + var proxy = new ProxyFactory().CreateProxy(typeof(PersistentGenericBag), null, typeof(ILazyInitializedCollection)); + Assert.That(proxy, Is.Not.Null); + + foreach (var method in proxy.GetType().GetMethods().Where(m => m.DeclaringType == typeof(ILazyInitializedCollection))) + { + // These attributes are what .NET uses for explicitly implemented interface methods + Assert.That(method.Attributes, Is.EqualTo(MethodAttributes.Private | + MethodAttributes.Final | + MethodAttributes.Virtual | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.SpecialName)); + } + } + } +} diff --git a/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs b/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs index ad0a79a60c3..c57e4e28e7a 100644 --- a/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs +++ b/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs @@ -118,7 +118,7 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, IReadOnlyCollecti // Provide a custom implementation of ISerializable // instead of redirecting it back to the interceptor - foreach (MethodInfo method in ProxyBuilderHelper.GetProxiableMethods(baseType, interfaces).Where(method => method.DeclaringType != typeof(ISerializable))) + foreach (MethodInfo method in ProxyBuilderHelper.GetProxiableMethods(parentType, interfaces).Where(method => method.DeclaringType != typeof(ISerializable))) { ProxyMethodBuilder.CreateProxiedMethod(interceptorField, method, typeBuilder); } diff --git a/src/NHibernate/Proxy/ProxyBuilderHelper.cs b/src/NHibernate/Proxy/ProxyBuilderHelper.cs index 94af19db95d..df32f3d06b4 100644 --- a/src/NHibernate/Proxy/ProxyBuilderHelper.cs +++ b/src/NHibernate/Proxy/ProxyBuilderHelper.cs @@ -137,7 +137,24 @@ internal static MethodBuilder GetObjectDataMethodBuilder(TypeBuilder typeBuilder internal static MethodBuilder GenerateMethodSignature(string name, MethodInfo method, TypeBuilder typeBuilder) { //TODO: Should we use attributes of base method? - var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual; + MethodAttributes methodAttributes; + if (method.DeclaringType.IsInterface) + { + // These are the attributes used for an explicit interface method implementation in .NET. + methodAttributes = + MethodAttributes.Private | + MethodAttributes.Final | + MethodAttributes.Virtual | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.SpecialName; + // .NET uses an expanded name for explicit interface implementation methods. + name = typeBuilder.FullName + "." + method.DeclaringType.FullName + "." + name; + } + else + { + methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual; + } if (method.IsSpecialName) methodAttributes |= MethodAttributes.SpecialName;