Skip to content

Commit 43c5fce

Browse files
authoredMay 9, 2023
Fix building proxies for classess with static interface members (#3298)
Fixes #3295
1 parent ed7a6d8 commit 43c5fce

File tree

2 files changed

+49
-6
lines changed

2 files changed

+49
-6
lines changed
 

‎src/NHibernate.Test/StaticProxyTest/StaticProxyFactoryFixture.cs

+44
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,50 @@ private static BinaryFormatter GetFormatter()
816816
#endif
817817
}
818818

819+
#if NETCOREAPP3_1_OR_GREATER
820+
public interface IWithStaticMethods
821+
{
822+
// C# 8
823+
static void StaticMethod()
824+
{
825+
}
826+
827+
#if NET7_0_OR_GREATER
828+
// C# 11
829+
static abstract void StaticAbstractMethod();
830+
831+
// C# 11
832+
static virtual void StaticVirtualMethod()
833+
{
834+
}
835+
#endif
836+
}
837+
838+
public class ClassWithStaticInterfaceMethods : IWithStaticMethods
839+
{
840+
public static void StaticAbstractMethod()
841+
{
842+
}
843+
}
844+
845+
[Test(Description = "GH3295")]
846+
public void VerifyProxyForClassWithStaticInterfaceMethod()
847+
{
848+
var factory = new StaticProxyFactory();
849+
factory.PostInstantiate(
850+
typeof(ClassWithStaticInterfaceMethods).FullName,
851+
typeof(ClassWithStaticInterfaceMethods),
852+
new HashSet<System.Type> { typeof(INHibernateProxy) },
853+
null, null, null, true);
854+
855+
var proxy = factory.GetProxy(1, null);
856+
Assert.That(proxy, Is.Not.Null);
857+
Assert.That(proxy, Is.InstanceOf<ClassWithStaticInterfaceMethods>());
858+
859+
Assert.That(factory.GetFieldInterceptionProxy(), Is.InstanceOf<ClassWithStaticInterfaceMethods>());
860+
}
861+
#endif
862+
819863
#if NETFX
820864
private static void VerifyGeneratedAssembly(System.Action assemblyGenerator)
821865
{

‎src/NHibernate/Proxy/ProxyBuilderHelper.cs

+5-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ namespace NHibernate.Proxy
2121
{
2222
internal static class ProxyBuilderHelper
2323
{
24+
private const BindingFlags ProxiableMethodsBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
25+
2426
private static readonly ConstructorInfo ObjectConstructor = typeof(object).GetConstructor(System.Type.EmptyTypes);
2527
private static readonly ConstructorInfo SecurityCriticalAttributeConstructor = typeof(SecurityCriticalAttribute).GetConstructor(System.Type.EmptyTypes);
2628
private static readonly ConstructorInfo IgnoresAccessChecksToAttributeConstructor = typeof(IgnoresAccessChecksToAttribute).GetConstructor(new[] {typeof(string)});
@@ -94,23 +96,20 @@ internal static void CallDefaultBaseConstructor(ILGenerator il, System.Type pare
9496

9597
internal static IEnumerable<MethodInfo> GetProxiableMethods(System.Type type)
9698
{
97-
const BindingFlags candidateMethodsBindingFlags =
98-
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
99-
100-
return type.GetMethods(candidateMethodsBindingFlags).Where(m => m.IsProxiable());
99+
return type.GetMethods(ProxiableMethodsBindingFlags).Where(m => m.IsProxiable());
101100
}
102101

103102
internal static IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerable<System.Type> interfaces)
104103
{
105104
if (type.IsInterface || type == typeof(object) || type.GetInterfaces().Length == 0)
106105
{
107106
return GetProxiableMethods(type)
108-
.Concat(interfaces.SelectMany(i => i.GetMethods()))
107+
.Concat(interfaces.SelectMany(i => i.GetMethods(ProxiableMethodsBindingFlags)))
109108
.Distinct();
110109
}
111110

112111
var proxiableMethods = new HashSet<MethodInfo>(GetProxiableMethods(type), new MethodInfoComparer(type));
113-
foreach (var interfaceMethod in interfaces.SelectMany(i => i.GetMethods()))
112+
foreach (var interfaceMethod in interfaces.SelectMany(i => i.GetMethods(ProxiableMethodsBindingFlags)))
114113
{
115114
proxiableMethods.Add(interfaceMethod);
116115
}

0 commit comments

Comments
 (0)
Please sign in to comment.