@@ -36,7 +36,16 @@ public NHibernateProxyBuilder(MethodInfo getIdentifierMethod, MethodInfo setIden
36
36
37
37
public TypeInfo CreateProxyType ( System . Type baseType , IReadOnlyCollection < System . Type > baseInterfaces )
38
38
{
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";
40
49
var assemblyName = $ "{ typeName } Assembly";
41
50
var moduleName = $ "{ typeName } Module";
42
51
@@ -77,7 +86,7 @@ public TypeInfo CreateProxyType(System.Type baseType, IReadOnlyCollection<System
77
86
// Provide a custom implementation of ISerializable instead of redirecting it back to the interceptor
78
87
foreach ( var method in ProxyBuilderHelper . GetProxiableMethods ( baseType , interfaces . Except ( new [ ] { typeof ( ISerializable ) } ) ) )
79
88
{
80
- CreateProxiedMethod ( typeBuilder , method , lazyInitializerField ) ;
89
+ CreateProxiedMethod ( typeBuilder , method , lazyInitializerField , parentType ) ;
81
90
}
82
91
83
92
ProxyBuilderHelper . MakeProxySerializable ( typeBuilder ) ;
@@ -91,19 +100,20 @@ public TypeInfo CreateProxyType(System.Type baseType, IReadOnlyCollection<System
91
100
return proxyType ;
92
101
}
93
102
94
- private void CreateProxiedMethod ( TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField )
103
+ private void CreateProxiedMethod (
104
+ TypeBuilder typeBuilder , MethodInfo method , FieldInfo lazyInitializerField , System . Type parentType )
95
105
{
96
106
if ( method == NHibernateProxyTypeLazyInitializerProperty . GetMethod )
97
107
{
98
108
ImplementGetLazyInitializer ( typeBuilder , method , lazyInitializerField ) ;
99
109
}
100
110
else if ( method == _getIdentifierMethod )
101
111
{
102
- ImplementGetIdentifier ( typeBuilder , method , lazyInitializerField ) ;
112
+ ImplementGetIdentifier ( typeBuilder , method , lazyInitializerField , parentType ) ;
103
113
}
104
114
else if ( method == _setIdentifierMethod )
105
115
{
106
- ImplementSetIdentifier ( typeBuilder , method , lazyInitializerField ) ;
116
+ ImplementSetIdentifier ( typeBuilder , method , lazyInitializerField , parentType ) ;
107
117
}
108
118
else if ( ! _overridesEquals && method . Name == "Equals" && method . GetBaseDefinition ( ) == typeof ( object ) . GetMethod ( "Equals" , new [ ] { typeof ( object ) } ) )
109
119
{
@@ -115,11 +125,11 @@ private void CreateProxiedMethod(TypeBuilder typeBuilder, MethodInfo method, Fie
115
125
}
116
126
else if ( _componentIdType != null && _componentIdType . IsMethodOf ( method ) )
117
127
{
118
- ImplementCallMethodOnEmbeddedComponentId ( typeBuilder , method , lazyInitializerField ) ;
128
+ ImplementCallMethodOnEmbeddedComponentId ( typeBuilder , method , lazyInitializerField , parentType ) ;
119
129
}
120
130
else
121
131
{
122
- ImplementCallMethodOnImplementation ( typeBuilder , method , lazyInitializerField ) ;
132
+ ImplementCallMethodOnImplementation ( typeBuilder , method , lazyInitializerField , parentType ) ;
123
133
}
124
134
}
125
135
@@ -217,7 +227,8 @@ private static void ImplementGetLazyInitializer(TypeBuilder typeBuilder, MethodI
217
227
typeBuilder . DefineMethodOverride ( getMethod , method ) ;
218
228
}
219
229
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 )
221
232
{
222
233
/*
223
234
get
@@ -231,7 +242,7 @@ private static void ImplementGetIdentifier(TypeBuilder typeBuilder, MethodInfo m
231
242
232
243
var IL = methodOverride . GetILGenerator ( ) ;
233
244
234
- EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField ) ;
245
+ EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField , parentType ) ;
235
246
236
247
IL . Emit ( OpCodes . Ldarg_0 ) ;
237
248
IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
@@ -242,10 +253,11 @@ private static void ImplementGetIdentifier(TypeBuilder typeBuilder, MethodInfo m
242
253
typeBuilder . DefineMethodOverride ( methodOverride , method ) ;
243
254
}
244
255
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 )
246
258
{
247
259
/*
248
- set
260
+ set
249
261
{
250
262
if (this.__lazyInitializer == null)
251
263
return base.set_<Identifier>(value);
@@ -258,7 +270,7 @@ private static void ImplementSetIdentifier(TypeBuilder typeBuilder, MethodInfo m
258
270
var methodOverride = ProxyBuilderHelper . GenerateMethodSignature ( method . Name , method , typeBuilder ) ;
259
271
var IL = methodOverride . GetILGenerator ( ) ;
260
272
261
- EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField ) ;
273
+ EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField , parentType ) ;
262
274
263
275
IL . Emit ( OpCodes . Ldarg_0 ) ;
264
276
IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
@@ -278,7 +290,8 @@ private static void ImplementSetIdentifier(TypeBuilder typeBuilder, MethodInfo m
278
290
typeBuilder . DefineMethodOverride ( methodOverride , method ) ;
279
291
}
280
292
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 )
282
295
{
283
296
/*
284
297
if (this.__lazyInitializer == null)
@@ -289,7 +302,7 @@ private static void ImplementCallMethodOnEmbeddedComponentId(TypeBuilder typeBui
289
302
290
303
var IL = methodOverride . GetILGenerator ( ) ;
291
304
292
- EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField ) ;
305
+ EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField , parentType ) ;
293
306
294
307
IL . Emit ( OpCodes . Ldarg_0 ) ;
295
308
IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
@@ -301,29 +314,46 @@ private static void ImplementCallMethodOnEmbeddedComponentId(TypeBuilder typeBui
301
314
typeBuilder . DefineMethodOverride ( methodOverride , method ) ;
302
315
}
303
316
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 )
305
319
{
306
320
/*
307
321
if (this.__lazyInitializer == null)
308
322
return base.<Method>(args..);
309
- return this.__lazyInitializer.GetImplementation().<Method>(args..)
323
+ return this.__lazyInitializer.GetImplementation().<Method>(args..)
310
324
*/
311
325
var methodOverride = ProxyBuilderHelper . GenerateMethodSignature ( method . Name , method , typeBuilder ) ;
312
326
313
327
var IL = methodOverride . GetILGenerator ( ) ;
314
328
315
- EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField ) ;
329
+ EmitCallBaseIfLazyInitializerIsNull ( IL , method , lazyInitializerField , parentType ) ;
316
330
317
331
EmitCallImplementation ( IL , method , lazyInitializerField ) ;
318
332
IL . Emit ( OpCodes . Ret ) ;
319
333
320
334
typeBuilder . DefineMethodOverride ( methodOverride , method ) ;
321
335
}
322
336
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 )
324
339
{
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.
327
357
328
358
IL . Emit ( OpCodes . Ldarg_0 ) ;
329
359
IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
0 commit comments