Skip to content

Commit 5822c8e

Browse files
committed
Explicitly implement INHibernateProxy
1 parent 4c6293a commit 5822c8e

File tree

5 files changed

+54
-10
lines changed

5 files changed

+54
-10
lines changed

src/NHibernate/Proxy/DefaultProxyFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public override INHibernateProxy GetProxy(object id, ISessionImplementor session
1818

1919
object proxyInstance = IsClassProxy
2020
? factory.CreateProxy(PersistentClass, initializer, Interfaces)
21-
: factory.CreateProxy(Interfaces[0], initializer, Interfaces);
21+
: factory.CreateProxy(typeof(object), initializer, Interfaces);
2222

2323
return (INHibernateProxy) proxyInstance;
2424
}
@@ -35,4 +35,4 @@ public override object GetFieldInterceptionProxy(object instanceToWrap)
3535
return factory.CreateProxy(PersistentClass, interceptor, new[] { typeof(IFieldInterceptorAccessor) });
3636
}
3737
}
38-
}
38+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System.Reflection;
2+
using System.Reflection.Emit;
3+
4+
namespace NHibernate.Proxy.DynamicProxy
5+
{
6+
class NHibernateProxyImplementor
7+
{
8+
const MethodAttributes InterceptorMethodsAttributes = MethodAttributes.Private | MethodAttributes.Final | MethodAttributes.HideBySig |
9+
MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual;
10+
11+
const string HibernateLazyInitializerFieldName = nameof(INHibernateProxy.HibernateLazyInitializer);
12+
13+
static readonly System.Type ReturnType = typeof(ILazyInitializer);
14+
static readonly System.Type NHibernateProxyType = typeof(INHibernateProxy);
15+
static readonly PropertyInfo OriginalGetter = NHibernateProxyType.GetProperty(HibernateLazyInitializerFieldName);
16+
static readonly MethodInfo OriginalGetterGetMethod = OriginalGetter.GetMethod;
17+
18+
public static void ImplementProxy(TypeBuilder typeBuilder, FieldInfo interceptor)
19+
{
20+
// Implement the getter
21+
var getMethod = typeBuilder.DefineMethod($"{NHibernateProxyType.FullName}.get_{HibernateLazyInitializerFieldName}", InterceptorMethodsAttributes, CallingConventions.HasThis, ReturnType, System.Type.EmptyTypes);
22+
getMethod.SetImplementationFlags(MethodImplAttributes.Managed | MethodImplAttributes.IL);
23+
24+
var IL = getMethod.GetILGenerator();
25+
26+
// This is equivalent to:
27+
// get { return (INHibernateProxy)__interceptor; }
28+
IL.Emit(OpCodes.Ldarg_0);
29+
IL.Emit(OpCodes.Ldfld, interceptor);
30+
IL.Emit(OpCodes.Castclass, ReturnType);
31+
IL.Emit(OpCodes.Ret);
32+
33+
typeBuilder.DefineMethodOverride(getMethod, OriginalGetterGetMethod);
34+
var property = typeBuilder.DefineProperty($"{NHibernateProxyType.FullName}.{HibernateLazyInitializerFieldName}", OriginalGetter.Attributes, ReturnType, System.Type.EmptyTypes);
35+
property.SetGetMethod(getMethod);
36+
}
37+
}
38+
}

src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66

77
#endregion
88

9+
using System;
10+
911
namespace NHibernate.Proxy.DynamicProxy
1012
{
13+
//Since v5.1
14+
[Obsolete]
1115
public class ProxyDummy
1216
{
1317
/* No Implementation */
1418
}
15-
}
19+
}

src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
112112
System.Type parentType = baseType;
113113
if (baseType.IsInterface)
114114
{
115-
parentType = typeof (ProxyDummy);
115+
parentType = typeof(object);
116116
interfaces.Add(baseType);
117117
}
118118

@@ -135,14 +135,20 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
135135
implementor.ImplementProxy(typeBuilder);
136136

137137
FieldInfo interceptorField = implementor.InterceptorField;
138+
138139

139140
// Provide a custom implementation of ISerializable
140141
// instead of redirecting it back to the interceptor
141-
foreach (MethodInfo method in GetProxiableMethods(baseType, interfaces).Where(method => method.DeclaringType != typeof(ISerializable)))
142+
foreach (MethodInfo method in GetProxiableMethods(baseType, interfaces.Except(new[] {typeof(ISerializable), typeof(INHibernateProxy)})))
142143
{
143144
ProxyMethodBuilder.CreateProxiedMethod(interceptorField, method, typeBuilder);
144145
}
145146

147+
if (interfaces.Contains(typeof(INHibernateProxy)))
148+
{
149+
NHibernateProxyImplementor.ImplementProxy(typeBuilder, interceptorField);
150+
}
151+
146152
// Make the proxy serializable
147153
AddSerializationSupport(baseType, baseInterfaces, typeBuilder, interceptorField, defaultConstructor);
148154
TypeInfo proxyType = typeBuilder.CreateTypeInfo();
@@ -304,4 +310,4 @@ private static void AddSerializationSupport(System.Type baseType, System.Type[]
304310
ImplementGetObjectData(baseType, baseInterfaces, typeBuilder, interceptorField);
305311
}
306312
}
307-
}
313+
}

src/NHibernate/Proxy/Poco/BasicLazyInitializer.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,6 @@ public virtual object Invoke(MethodInfo method, object[] args, object proxy)
8181
{
8282
return null;
8383
}
84-
else if ("get_HibernateLazyInitializer".Equals(methodName))
85-
{
86-
return this;
87-
}
8884
}
8985
else if (paramCount == 1)
9086
{

0 commit comments

Comments
 (0)