@@ -24,6 +24,7 @@ internal class NHibernateProxyBuilder
2424 private static readonly PropertyInfo LazyInitializerIdentifierProperty = LazyInitializerType . GetProperty ( nameof ( ILazyInitializer . Identifier ) ) ;
2525 private static readonly MethodInfo LazyInitializerInitializeMethod = LazyInitializerType . GetMethod ( nameof ( ILazyInitializer . Initialize ) ) ;
2626 private static readonly MethodInfo LazyInitializerGetImplementationMethod = LazyInitializerType . GetMethod ( nameof ( ILazyInitializer . GetImplementation ) , System . Type . EmptyTypes ) ;
27+ private static readonly PropertyInfo LazyInitializerIsUninitializedProperty = LazyInitializerType . GetProperty ( nameof ( ILazyInitializer . IsUninitialized ) ) ;
2728 private static readonly IProxyAssemblyBuilder ProxyAssemblyBuilder = new DefaultProxyAssemblyBuilder ( ) ;
2829
2930 private static readonly ConstructorInfo SecurityCriticalAttributeConstructor = typeof ( SecurityCriticalAttribute ) . GetConstructor ( System . Type . EmptyTypes ) ;
@@ -95,7 +96,7 @@ public TypeInfo CreateProxyType(System.Type baseType, IReadOnlyCollection<System
9596 var customAttributeBuilder = new CustomAttributeBuilder ( serializableConstructor , Array . Empty < object > ( ) ) ;
9697 typeBuilder . SetCustomAttribute ( customAttributeBuilder ) ;
9798
98- ImplementDeserializationConstructor ( typeBuilder ) ;
99+ ImplementDeserializationConstructor ( typeBuilder , parentType ) ;
99100 ImplementGetObjectData ( typeBuilder , proxyInfoField , lazyInitializerField ) ;
100101
101102 var proxyType = typeBuilder . CreateTypeInfo ( ) ;
@@ -168,13 +169,24 @@ private static void ImplementConstructor(TypeBuilder typeBuilder, System.Type pa
168169 IL . Emit ( OpCodes . Ret ) ;
169170 }
170171
171- private static void ImplementDeserializationConstructor ( TypeBuilder typeBuilder )
172+ private static void ImplementDeserializationConstructor ( TypeBuilder typeBuilder , System . Type parentType )
172173 {
173174 var parameterTypes = new [ ] { typeof ( SerializationInfo ) , typeof ( StreamingContext ) } ;
174175 var constructor = typeBuilder . DefineConstructor ( constructorAttributes , CallingConventions . Standard , parameterTypes ) ;
175176 constructor . SetImplementationFlags ( MethodImplAttributes . IL | MethodImplAttributes . Managed ) ;
176177
177178 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+
178190 //Everything is done in NHibernateProxyObjectReference, so just return data.
179191 IL . Emit ( OpCodes . Ret ) ;
180192 }
@@ -199,7 +211,12 @@ private static void ImplementGetObjectData(TypeBuilder typeBuilder, FieldInfo pr
199211 IL . Emit ( OpCodes . Call , ReflectionCache . TypeMethods . GetTypeFromHandle ) ;
200212 IL . Emit ( OpCodes . Callvirt , SerializationInfoSetTypeMethod ) ;
201213
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);
203220 //this.__proxyInfo
204221 IL . Emit ( OpCodes . Ldarg_0 ) ;
205222 IL . Emit ( OpCodes . Ldfld , proxyInfoField ) ;
@@ -209,11 +226,27 @@ private static void ImplementGetObjectData(TypeBuilder typeBuilder, FieldInfo pr
209226 IL . Emit ( OpCodes . Ldfld , lazyInitializerField ) ;
210227 IL . Emit ( OpCodes . Callvirt , LazyInitializerIdentifierProperty . GetMethod ) ;
211228
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+
212244 var constructor = typeof ( NHibernateProxyObjectReference ) . GetConstructor (
213245 new [ ]
214246 {
215247 typeof ( NHibernateProxyFactoryInfo ) ,
216248 typeof ( object ) ,
249+ typeof ( object )
217250 } ) ;
218251 IL . Emit ( OpCodes . Newobj , constructor ) ;
219252
0 commit comments