@@ -36,7 +36,16 @@ public NHibernateProxyBuilder(MethodInfo getIdentifierMethod, MethodInfo setIden
3636
3737 public TypeInfo CreateProxyType ( System . Type baseType , IReadOnlyCollection < System . Type > baseInterfaces )
3838 {
39- var typeName = $ "{ baseType . Name } Proxy";
39+ System . Type interfaceType = null ;
40+ if ( baseType == typeof ( object ) )
41+ {
42+ // Mapping option "proxy" allows to ask for using an interface, which switches the base type to object
43+ // and adds the interface to base interfaces set.
44+ // Avoids using object for naming the proxy, as otherwise all entities using the "proxy" option for
45+ // specifying an interface would have their proxies sharing the same full name.
46+ interfaceType = baseInterfaces . FirstOrDefault ( i => i != typeof ( INHibernateProxy ) ) ;
47+ }
48+ var typeName = $ "{ ( interfaceType ?? baseType ) . Name } Proxy";
4049 var assemblyName = $ "{ typeName } Assembly";
4150 var moduleName = $ "{ typeName } Module";
4251
@@ -77,7 +86,7 @@ public TypeInfo CreateProxyType(System.Type baseType, IReadOnlyCollection<System
7786 // Provide a custom implementation of ISerializable instead of redirecting it back to the interceptor
7887 foreach ( var method in ProxyBuilderHelper . GetProxiableMethods ( baseType , interfaces . Except ( new [ ] { typeof ( ISerializable ) } ) ) )
7988 {
80- CreateProxiedMethod ( typeBuilder , method , lazyInitializerField ) ;
89+ CreateProxiedMethod ( typeBuilder , method , lazyInitializerField , parentType ) ;
8190 }
8291
8392 ProxyBuilderHelper . MakeProxySerializable ( typeBuilder ) ;
@@ -91,19 +100,20 @@ public TypeInfo CreateProxyType(System.Type baseType, IReadOnlyCollection<System
91100 return proxyType ;
92101 }
93102
94- private void CreateProxiedMethod ( TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField )
103+ private void CreateProxiedMethod (
104+ TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField , System . Type parentType )
95105 {
96106 if ( method == NHibernateProxyTypeLazyInitializerProperty . GetMethod )
97107 {
98108 ImplementGetLazyInitializer ( typeBuilder , method , lazyInitializerField ) ;
99109 }
100110 else if ( method == _getIdentifierMethod )
101111 {
102- ImplementGetIdentifier ( typeBuilder , method , lazyInitializerField ) ;
112+ ImplementGetIdentifier ( typeBuilder , method , lazyInitializerField , parentType ) ;
103113 }
104114 else if ( method == _setIdentifierMethod )
105115 {
106- ImplementSetIdentifier ( typeBuilder , method , lazyInitializerField ) ;
116+ ImplementSetIdentifier ( typeBuilder , method , lazyInitializerField , parentType ) ;
107117 }
108118 else if ( ! _overridesEquals && method . Name == "Equals" && method . GetBaseDefinition ( ) == typeof ( object ) . GetMethod ( "Equals" , new [ ] { typeof ( object ) } ) )
109119 {
@@ -115,11 +125,11 @@ private void CreateProxiedMethod(TypeBuilder typeBuilder, MethodInfo method, Fie
115125 }
116126 else if ( _componentIdType != null && _componentIdType . IsMethodOf ( method ) )
117127 {
118- ImplementCallMethodOnEmbeddedComponentId ( typeBuilder , method , lazyInitializerField ) ;
128+ ImplementCallMethodOnEmbeddedComponentId ( typeBuilder , method , lazyInitializerField , parentType ) ;
119129 }
120130 else
121131 {
122- ImplementCallMethodOnImplementation ( typeBuilder , method , lazyInitializerField ) ;
132+ ImplementCallMethodOnImplementation ( typeBuilder , method , lazyInitializerField , parentType ) ;
123133 }
124134 }
125135
@@ -217,7 +227,8 @@ private static void ImplementGetLazyInitializer(TypeBuilder typeBuilder, MethodI
217227 typeBuilder . DefineMethodOverride ( getMethod , method ) ;
218228 }
219229
220- private static void ImplementGetIdentifier ( TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField )
230+ private static void ImplementGetIdentifier (
231+ TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField , System . Type parentType )
221232 {
222233 /*
223234 get
@@ -231,7 +242,7 @@ private static void ImplementGetIdentifier(TypeBuilder typeBuilder, MethodInfo m
231242
232243 var IL = methodOverride . GetILGenerator ( ) ;
233244
234- EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField ) ;
245+ EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField , parentType ) ;
235246
236247 IL . Emit ( OpCodes . Ldarg_0 ) ;
237248 IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
@@ -242,10 +253,11 @@ private static void ImplementGetIdentifier(TypeBuilder typeBuilder, MethodInfo m
242253 typeBuilder . DefineMethodOverride ( methodOverride , method ) ;
243254 }
244255
245- private static void ImplementSetIdentifier ( TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField )
256+ private static void ImplementSetIdentifier (
257+ TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField , System . Type parentType )
246258 {
247259 /*
248- set
260+ set
249261 {
250262 if (this.__lazyInitializer == null)
251263 return base.set_<Identifier>(value);
@@ -258,7 +270,7 @@ private static void ImplementSetIdentifier(TypeBuilder typeBuilder, MethodInfo m
258270 var methodOverride = ProxyBuilderHelper . GenerateMethodSignature ( method . Name , method , typeBuilder ) ;
259271 var IL = methodOverride . GetILGenerator ( ) ;
260272
261- EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField ) ;
273+ EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField , parentType ) ;
262274
263275 IL . Emit ( OpCodes . Ldarg_0 ) ;
264276 IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
@@ -278,7 +290,8 @@ private static void ImplementSetIdentifier(TypeBuilder typeBuilder, MethodInfo m
278290 typeBuilder . DefineMethodOverride ( methodOverride , method ) ;
279291 }
280292
281- private static void ImplementCallMethodOnEmbeddedComponentId ( TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField )
293+ private static void ImplementCallMethodOnEmbeddedComponentId (
294+ TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField , System . Type parentType )
282295 {
283296 /*
284297 if (this.__lazyInitializer == null)
@@ -289,7 +302,7 @@ private static void ImplementCallMethodOnEmbeddedComponentId(TypeBuilder typeBui
289302
290303 var IL = methodOverride . GetILGenerator ( ) ;
291304
292- EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField ) ;
305+ EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField , parentType ) ;
293306
294307 IL . Emit ( OpCodes . Ldarg_0 ) ;
295308 IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
@@ -301,29 +314,46 @@ private static void ImplementCallMethodOnEmbeddedComponentId(TypeBuilder typeBui
301314 typeBuilder . DefineMethodOverride ( methodOverride , method ) ;
302315 }
303316
304- private static void ImplementCallMethodOnImplementation ( TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField )
317+ private static void ImplementCallMethodOnImplementation (
318+ TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField , System . Type parentType )
305319 {
306320 /*
307321 if (this.__lazyInitializer == null)
308322 return base.<Method>(args..);
309- return this.__lazyInitializer.GetImplementation().<Method>(args..)
323+ return this.__lazyInitializer.GetImplementation().<Method>(args..)
310324 */
311325 var methodOverride = ProxyBuilderHelper . GenerateMethodSignature ( method . Name , method , typeBuilder ) ;
312326
313327 var IL = methodOverride . GetILGenerator ( ) ;
314328
315- EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField ) ;
329+ EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField , parentType ) ;
316330
317331 EmitCallImplementation ( IL , method , lazyInitializerField ) ;
318332 IL . Emit ( OpCodes . Ret ) ;
319333
320334 typeBuilder . DefineMethodOverride ( methodOverride , method ) ;
321335 }
322336
323- private static void EmitCallBaseIfLazyInitializerIsNull ( ILGenerator IL , MethodInfo method , FieldInfo lazyInitializerField )
337+ private static void EmitCallBaseIfLazyInitializerIsNull (
338+ ILGenerator IL , MethodInfo method , FieldInfo lazyInitializerField , System . Type parentType )
324339 {
325- //if (this.__lazyInitializer == null)
326- // return base.<Method>(args..)
340+ /*
341+ <if (method.DeclaringType.IsAssignableFrom(parentType))
342+ {>
343+ if (this.__lazyInitializer == null)
344+ return base.<method>(args..)
345+ <}>
346+ */
347+ if ( ! method . DeclaringType . IsAssignableFrom ( parentType ) )
348+ // The proxy does not derive from a type implementing the method, do not attempt
349+ // calling its base. In such case, the lazy initializer is never null.
350+ return ;
351+
352+ // When deriving from the entity class, the entity class constructor may trigger
353+ // virtual calls accessing the proxy state before its own constructor has a chance
354+ // to initialize it. So although lazyInitializer is never supplied as null to the
355+ // proxy constructor, we must guard nonetheless against it being null during base
356+ // constructor call.
327357
328358 IL . Emit ( OpCodes . Ldarg_0 ) ;
329359 IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
0 commit comments