Skip to content

Commit 46477d6

Browse files
committed
Explicitly implement INHibernateProxy
1 parent 4c6293a commit 46477d6

File tree

5 files changed

+55
-17
lines changed

5 files changed

+55
-17
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: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,6 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
109109

110110
// Use the proxy dummy as the base type
111111
// since we're not inheriting from any class type
112-
System.Type parentType = baseType;
113-
if (baseType.IsInterface)
114-
{
115-
parentType = typeof (ProxyDummy);
116-
interfaces.Add(baseType);
117-
}
118112

119113
// Add any inherited interfaces
120114
System.Type[] computedInterfaces = interfaces.ToArray();
@@ -126,23 +120,29 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
126120
// Add the ISerializable interface so that it can be implemented
127121
interfaces.Add(typeof (ISerializable));
128122

129-
TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, typeAttributes, parentType, interfaces.ToArray());
123+
TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, typeAttributes, baseType, interfaces.ToArray());
130124

131-
ConstructorBuilder defaultConstructor = DefineConstructor(typeBuilder, parentType);
125+
ConstructorBuilder defaultConstructor = DefineConstructor(typeBuilder, baseType);
132126

133127
// Implement IProxy
134128
var implementor = new ProxyImplementor();
135129
implementor.ImplementProxy(typeBuilder);
136130

137131
FieldInfo interceptorField = implementor.InterceptorField;
132+
138133

139134
// Provide a custom implementation of ISerializable
140135
// instead of redirecting it back to the interceptor
141-
foreach (MethodInfo method in GetProxiableMethods(baseType, interfaces).Where(method => method.DeclaringType != typeof(ISerializable)))
136+
foreach (MethodInfo method in GetProxiableMethods(baseType, interfaces.Except(new[] {typeof(ISerializable), typeof(INHibernateProxy)})))
142137
{
143138
ProxyMethodBuilder.CreateProxiedMethod(interceptorField, method, typeBuilder);
144139
}
145140

141+
if (interfaces.Contains(typeof(INHibernateProxy)))
142+
{
143+
NHibernateProxyImplementor.ImplementProxy(typeBuilder, interceptorField);
144+
}
145+
146146
// Make the proxy serializable
147147
AddSerializationSupport(baseType, baseInterfaces, typeBuilder, interceptorField, defaultConstructor);
148148
TypeInfo proxyType = typeBuilder.CreateTypeInfo();
@@ -304,4 +304,4 @@ private static void AddSerializationSupport(System.Type baseType, System.Type[]
304304
ImplementGetObjectData(baseType, baseInterfaces, typeBuilder, interceptorField);
305305
}
306306
}
307-
}
307+
}

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)