I desperately need the ability to call overridden Equals, GetHashCode and ToString methods on my proxy objects without causing them to be initialized.
Given that I can guarantee that these methods will not touch any local class fields, I don't see how this could break anything.
If they really need to touch a virtual property, the proxy will be initialized anyway.
The main reason why I need this is because I'm managing to get references the real versions of my objects (LazyInitializer._target), even though they should only ever be accessed through the proxy.
If I don't override Equals/GetHashCode, then I can't equate them or find them in hashtables.
If I do override Equals/GetHashCode, the moment I put them in a hashtable, they're all initialized.
The reason that I'm getting references to the initialized object is because I'm using Ayende's double linked collection pattern (
http://www.ayende.com/projects/nhibernate-query-analyzer/generics.aspx).
Taking the example from his webpage, whenever you add posts to a blog, the post's Blog property will be set to "this", ie the real object, not the proxy.
Code:
public Blog()
{
_posts = new EntitySet<Post>(
delegate(Post p) { p.Blog = this; },
delegate(Post p) { p.Blog = null; }
);
}
The following simple code should illustrate this:
Code:
Blog blog = session.Load<Blog>(id); // blog is a proxy
Post post = new Post();
blog.Add(post); // initialized and called on the real object
Debug.Assert(blog.ID == post.Blog.ID); // no problems here
Debug.Assert(blog == post.Blog); // this will fail!
Debug.Assert(Equals(blog, post.Blog)); // so will this unless I override
I was overjoyed when I learned of the "hibernate.use_proxy_validator" setting as this gave me the flexibility of choosing exactly which non-overridden methods cause initialization.
I'm probably asking for too much, but is there any way that another setting (like "bypass_object_proxy_methods") could be introduced at either a global or class level?
For now I've gotten around this by modifying line 49 in the latest SVN version of CastleLazyInitializer.cs.
Obviously I would really prefer if a more complete/permanent solution could be found.
this:
Code:
if( _constructed)
becomes:
Code:
string methodName = invocation.Method.Name;
int argCount = args.Length;
if( _constructed &&
!(methodName == "Equals" && argCount == 1) &&
!(methodName == "GetHashCode" && argCount == 0) &&
!(methodName == "ToString" && argCount == 0))
Any advice much appreciated.
Cheers.