Hi Patrick,
I made the change to make the generated assemblies pass PeVerify:
https://nhibernate.jira.com/browse/NH-2857
I’d agree with the argument that the (default) constructor that NH uses
shouldn’t be doing anything unusual, but obviously we can’t enforce that.
If there is now a situation that we can get a stack overflow using (just)
NHibernateUtil.IsInitialized, then that should probably be fixed. I’m not so
sure about casting the object directly to an IProxy and relying on the
underlying implementation of Interceptors though – it’s not clear to me how
someone would decide what is acceptable/reasonable external behaviour for that.
In addition, I think the original Castle proxy would have behaved like this
too?
Also, if you mark the default constructor as private, then the proxy has no
choice but to bypass it (and behave the way it did prior to that fix). Does
that help?
Cheers,
Richard
From: Patrick Earl
Sent: Tuesday, November 27, 2012 4:57 AM
To: nhibernate-development
Subject: [nhibernate-development] Calling base constructor in proxies
I noticed (due to a stack overflow) that proxies now call their base
constructor. That behaviour is a little scary to me since proxies are not real
objects and the real objects might have interaction with the world that isn't
supposed to happen with proxy objects. I suppose the argument could be made
that the constructor should not be doing anything remotely interesting, but on
the other hand, constructors should produce objects that don't need additional
initialization.
The stack overflow itself was from an interesting combination of changes in the
latest NH. First, it calls the base constructor. Second, the dynamic proxy
was changed to call "base.Method()" if the interceptor was not set. Since
there is no "base.Method()" I assume that it ends up calling the same method
again, resulting in the mysterious stack overflow.
Basically my code was doing something like NHibernateUtil.IsInitialized(a) and
when it went to get the HibernateLazyInitializer property it overflowed the
stack. I ended up fixing this by changing my condition as follows:
a is IProxy && (a as IProxy).Interceptor != null &&
NHibernateUtil.IsInitialized(a)
Perhaps the code to check for uninitialized proxies inside of NHibernateUtil
needs to be improved. Perhaps a flag could be present to disable calling the
base constructor when not needed for a medium trust environment. Thoughts on
this interesting situation? Has anyone else run into problems related to
calling the base constructor?
Patrick Earl