Hi,
I'm working on a proyect with NHibernate and LinFu, and I've found a problem caused due to LinFu's ProxyFactory overriding GetType() method on generated proxy.
My code is partially based on SharpArchitecture's code, which uses a base class (BaseObject) to define domain entity classes.
At this BaseObject class there's some trick at Equals() method which allows comparing a real object against a proxied one by calling "GetUnproxiedType()", which calls "GetType()" from whithin base class instead of from the finall one (the one being proxied by NH).
You can see the details here: (Look for Equals() and GetTypeUnproxied()) http://code.google.com/p/sharp-architecture/source/browse/trunk/src/SharpArch/SharpArch.Core/DomainModel/BaseObject.cs
The point is that this code is working fine with NHibernate+Castle, but fails with NHibernate+LinFu.
Is this an expected behaviour? Is there any workaround?
Thnks in advice.
Comment #1
Posted on Aug 20, 2009 by Massive BirdHi Pablo,
Yes, this is the expected behavior for LinFu.DynamicProxy. You can work around it by returning the actual object type in the intercepted GetType() call.
Comment #2
Posted on Aug 20, 2009 by Helpful LionAfter analyzing the problem, it seems related to the fact that LinFu it's not caching the generated Type it creates under the hood to instantiate the proxy..
So my two instances, even if both of them are proxy's, aren't of the same type.
Is this also, by design?
Comment #3
Posted on Aug 20, 2009 by Helpful LionThis is the code i'm using:
public class Class { public string Property { get; set; } }
public class Interceptor : IInterceptor
{
public object Intercept(InvocationInfo info)
{
return info.TargetMethod.Invoke(info.TargetMethod, info.Arguments);
}
}
void Main() { var obj1 = new Class(); var obj2 = (Class)new ProxyFactory().CreateProxy(typeof(Class), new Interceptor(), new Type[] {}); var obj3 = (Class)new ProxyFactory().CreateProxy(typeof(Class), new Interceptor(), new Type[] {});
obj1.GetType().Dump("Obj1");
obj2.GetType().Dump("Obj2");
obj3.GetType().Dump("Obj3");
(obj1.Equals(obj2)).Dump(); // Returns false
(obj1.GetType() == obj2.GetType()).Dump(); // Returns false
(obj1.Equals(obj3)).Dump(); // Returns false
(obj1.GetType() == obj3.GetType()).Dump(); // Returns false
(obj2.Equals(obj3)).Dump(); // Returns false
(obj2.GetType() == obj3.GetType()).Dump(); // Returns true
}
Comment #4
Posted on Aug 20, 2009 by Massive BirdTry:
var firstFactory = new ProxyFactory(); var secondFactory = new ProxyFactory();
var isSameType = firstFactory.CreateProxyType(typeof(Class)) == secondFactory.CreateProxyType(typeof(Class));
Is the isSameType variable true, or false? If it's true, that means the proxy caches types correctly. If it's false, then we definitely have a bug here
Comment #5
Posted on Aug 21, 2009 by Helpful LionIt's true.. definitly the error is not at linfu.
On new tests i've just made, I found NHibernate to behave differently when using LinFu, vs (Castle|Spring).
I'm trying to isolate my case with as few code as possible.. But right now, it is clear that with castle or spring it it's always generating proxies for my lazy objects. But when it comes to LinFu, it does not always generate proxy instances.. So, at some point a comparison between a proxy and a non-proxy is done.. and everything blows away...
Anyway, thank you very much for you help... and for your product (linfu).
I will go to blame (joke) nhibernate guys..
Comment #6
Posted on Aug 21, 2009 by Massive Bird(No comment was entered for this change.)
Comment #7
Posted on Aug 24, 2009 by Helpful LionHi, after analyzing the problen in depth, I found it to be a diferent behavior between castle, spring and Linfu.
Seems like LinFu (or the way NH is calling LinFu) does not override protected properties/members.
I've assembled a piece of code with relays on NH and compares the behaviour of castle, spring and linfu's proxy factories.
What I've found can be read here: http://nhjira.koah.net/browse/NH-1937?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel
However, I've not found documentation enough on howto override such behavior while instantiating a LinFu proxy.
Can you help me on this subject?
Thanks.
Comment #8
Posted on Aug 27, 2009 by Massive BirdLinFu.DynamicProxy v1.0 doesn't proxy protected/protected internal methods and properties, but that has been fixed with LinFu.Proxy (aka LinFu.DP2). Dario Quintana wrote an bytecode provider for the LinFu.Proxy and it passed all the NH tests, but I'm not sure if the NH team added LinFu.Proxy to the latest release of NH. You might want to check with them and see what happened with that.
Status: WontFix
Labels:
Type-Defect
Priority-Medium