@@ -24,6 +24,7 @@ internal class NHibernateProxyBuilder
24
24
private static readonly PropertyInfo LazyInitializerIdentifierProperty = LazyInitializerType . GetProperty ( nameof ( ILazyInitializer . Identifier ) ) ;
25
25
private static readonly MethodInfo LazyInitializerInitializeMethod = LazyInitializerType . GetMethod ( nameof ( ILazyInitializer . Initialize ) ) ;
26
26
private static readonly MethodInfo LazyInitializerGetImplementationMethod = LazyInitializerType . GetMethod ( nameof ( ILazyInitializer . GetImplementation ) , System . Type . EmptyTypes ) ;
27
+ private static readonly PropertyInfo LazyInitializerIsUninitializedProperty = LazyInitializerType . GetProperty ( nameof ( ILazyInitializer . IsUninitialized ) ) ;
27
28
private static readonly IProxyAssemblyBuilder ProxyAssemblyBuilder = new DefaultProxyAssemblyBuilder ( ) ;
28
29
29
30
private static readonly ConstructorInfo SecurityCriticalAttributeConstructor = typeof ( SecurityCriticalAttribute ) . GetConstructor ( System . Type . EmptyTypes ) ;
@@ -95,7 +96,7 @@ public TypeInfo CreateProxyType(System.Type baseType, IReadOnlyCollection<System
95
96
var customAttributeBuilder = new CustomAttributeBuilder ( serializableConstructor , Array . Empty < object > ( ) ) ;
96
97
typeBuilder . SetCustomAttribute ( customAttributeBuilder ) ;
97
98
98
- ImplementDeserializationConstructor ( typeBuilder ) ;
99
+ ImplementDeserializationConstructor ( typeBuilder , parentType ) ;
99
100
ImplementGetObjectData ( typeBuilder , proxyInfoField , lazyInitializerField ) ;
100
101
101
102
var proxyType = typeBuilder . CreateTypeInfo ( ) ;
@@ -168,13 +169,24 @@ private static void ImplementConstructor(TypeBuilder typeBuilder, System.Type pa
168
169
IL . Emit ( OpCodes . Ret ) ;
169
170
}
170
171
171
- private static void ImplementDeserializationConstructor ( TypeBuilder typeBuilder )
172
+ private static void ImplementDeserializationConstructor ( TypeBuilder typeBuilder , System . Type parentType )
172
173
{
173
174
var parameterTypes = new [ ] { typeof ( SerializationInfo ) , typeof ( StreamingContext ) } ;
174
175
var constructor = typeBuilder . DefineConstructor ( constructorAttributes , CallingConventions . Standard , parameterTypes ) ;
175
176
constructor . SetImplementationFlags ( MethodImplAttributes . IL | MethodImplAttributes . Managed ) ;
176
177
177
178
var IL = constructor . GetILGenerator ( ) ;
179
+
180
+ constructor . SetImplementationFlags ( MethodImplAttributes . IL | MethodImplAttributes . Managed ) ;
181
+
182
+ var baseConstructor = parentType . GetConstructor ( BindingFlags . Instance | BindingFlags . NonPublic | BindingFlags . Public , null , System . Type . EmptyTypes , null ) ;
183
+ // if there is no default constructor, or the default constructor is private/internal, call System.Object constructor
184
+ // this works, but the generated assembly will fail PeVerify (cannot use in medium trust for example)
185
+ if ( baseConstructor == null || baseConstructor . IsPrivate || baseConstructor . IsAssembly )
186
+ baseConstructor = ObjectConstructor ;
187
+ IL . Emit ( OpCodes . Ldarg_0 ) ;
188
+ IL . Emit ( OpCodes . Call , baseConstructor ) ;
189
+
178
190
//Everything is done in NHibernateProxyObjectReference, so just return data.
179
191
IL . Emit ( OpCodes . Ret ) ;
180
192
}
@@ -199,7 +211,12 @@ private static void ImplementGetObjectData(TypeBuilder typeBuilder, FieldInfo pr
199
211
IL . Emit ( OpCodes . Call , ReflectionCache . TypeMethods . GetTypeFromHandle ) ;
200
212
IL . Emit ( OpCodes . Callvirt , SerializationInfoSetTypeMethod ) ;
201
213
202
- // (new NHibernateProxyObjectReference(this.__proxyInfo, this.__lazyInitializer.Identifier)).GetObjectData(info, context);
214
+ // return
215
+ // (new NHibernateProxyObjectReference(
216
+ // this.__proxyInfo,
217
+ // this.__lazyInitializer.Identifier),
218
+ // this.__lazyInitializer.IsUninitialized ? null : this.__lazyInitializer.GetImplementation())
219
+ // .GetObjectData(info, context);
203
220
//this.__proxyInfo
204
221
IL . Emit ( OpCodes . Ldarg_0 ) ;
205
222
IL . Emit ( OpCodes . Ldfld , proxyInfoField ) ;
@@ -209,11 +226,27 @@ private static void ImplementGetObjectData(TypeBuilder typeBuilder, FieldInfo pr
209
226
IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
210
227
IL . Emit ( OpCodes . Callvirt , LazyInitializerIdentifierProperty . GetMethod ) ;
211
228
229
+ // this.__lazyInitializer.IsUninitialized ? null : this.__lazyInitializer.GetImplementation()
230
+ var isUnitialized = IL . DefineLabel ( ) ;
231
+ var endIsUnitializedTernary = IL . DefineLabel ( ) ;
232
+ IL . Emit ( OpCodes . Ldarg_0 ) ;
233
+ IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
234
+ IL . Emit ( OpCodes . Callvirt , LazyInitializerIsUninitializedProperty . GetMethod ) ;
235
+ IL . Emit ( OpCodes . Brtrue , isUnitialized ) ;
236
+ IL . Emit ( OpCodes . Ldarg_0 ) ;
237
+ IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
238
+ IL . Emit ( OpCodes . Callvirt , LazyInitializerGetImplementationMethod ) ;
239
+ IL . Emit ( OpCodes . Br , endIsUnitializedTernary ) ;
240
+ IL . MarkLabel ( isUnitialized ) ;
241
+ IL . Emit ( OpCodes . Ldnull ) ;
242
+ IL . MarkLabel ( endIsUnitializedTernary ) ;
243
+
212
244
var constructor = typeof ( NHibernateProxyObjectReference ) . GetConstructor (
213
245
new [ ]
214
246
{
215
247
typeof ( NHibernateProxyFactoryInfo ) ,
216
248
typeof ( object ) ,
249
+ typeof ( object )
217
250
} ) ;
218
251
IL . Emit ( OpCodes . Newobj , constructor ) ;
219
252
0 commit comments