识别NHibernate代理类
我不是NHibernate的用户; 我写了一个序列化实用程序库。 用户已经logging了一个function请求,我应该处理NHibernate代理类,将它们与实际types相同。 目前我的代码被视为意外的inheritance,并抛出一个exception。
该代码不会提前知道有关NHibernate(包括没有参考,但我不是反映; -p)
有检测这种代理types的强大/保证的方式? 显然DataContractSerializer
处理这个罚款,所以我希望这是非常简单的事情。 也许一些界面或[attribute]
装饰。
另外,在反序列化过程中, 此刻我会创build原始types(而不是NHibernatetypes)。 这是为了持久的目的吗? 还是需要代理types? 如果后者; 什么是需要创build一个代理types的实例?
你可以检测一个类是否是一个NHibernate代理,通过将它转换为INHibernateProxy
(不出意外)。
如果您需要获取底层的“真实”对象,请使用:
Session.GetSessionImplementation().PersistenceContext.Unproxy(proxiedObject)
您不需要testing代理来调用Unproxy
; 如果它不是代理,它将返回原始参数。
编辑:我现在使用不同的方法来获得底层对象,主要是为了解决延迟加载和inheritance: http : //sessionfactory.blogspot.com/2010/08/hacking-lazy-loaded-inheritance.html
我猜你不是真的想要访问实际的Nhibernate会话。 此代码可能更适合您的需求:
/// <summary> /// Returns the real type of the given proxy. If the object is not a proxy, it's normal type is returned. /// </summary> internal static Type GetRealType(this object proxy) { if (proxy is INHibernateProxy) { var lazyInitialiser = ((INHibernateProxy)proxy).HibernateLazyInitializer; return lazyInitialiser.PersistentClass; } else { return proxy.GetType(); } }
希望有所帮助。
有一个从NHibernate的工具,你给一个types(代理或不),它返回的实际types。 (我正在使用NHibernate 3)
这是你如何使用它:
var realType = NHibernate.NHibernateUtil.GetClass(proxyInstance);
希望这有助于:D
NHibernate在运行时创build(代理)原始实体的子类,以便能够进行延迟加载。 它只能做到这一点,因为你被迫标记所有的属性为“虚拟”。 我无法想象如何能够检测到一个对象是一个代理,而不是任何其他types的子类 – 当然不是一个通用的方式。 我只能假定你的代码在这种情况下抛出了一个exception,因为被(序列化)的实际类没有被标记为可序列化的。 我认为你唯一能做的就是放松你的validation,或者允许一个子类的序列化,如果它覆盖了它的基类的所有属性的话。
反序列化到原来的types将会很好。
NHibernate 2.1+允许通过configuration来设置dynamic代理提供程序。 我知道的实现是Castle(默认),LinFu和Spring。 NHibernate不需要接口或属性。 我认为这使得可靠地检测对象是否是代理是相当不可能的。
正如s1mm0t所回答的那样,在反序列化中创build实际types是很好的。
如果你正在编写一个通用的序列化工具库,我不认为你应该处理这个特定的案例。 你的代码不应该依赖于NHibernate。 你应该做的是提供钩子,客户端代码可以用来影响你的库的操作。
迭戈的方法在试图确定它的types之前完全加载对象 – 这绝对是最通用的方法,但是如果代理已经知道具体types,则可能不需要加载对象。
Vijay的方法在事先知道具体types的情况下更快 – 但正如Diego指出的那样,在某些情况下,由于确定确切types所需的信息尚未加载,所以信息不可用。
考虑到这两种情况,我想出了以下几点:
https://gist.github.com/1089489
有趣的是这样的:
if (entity is INHibernateProxy) { var lazyInitialiser = ((INHibernateProxy)entity).HibernateLazyInitializer; var type = lazyInitialiser.PersistentClass; if (type.IsAbstract || type.GetNestedTypes().Length > 0) return Service.Session.GetSessionImplementation().PersistenceContext.Unproxy(entity).GetType(); else // we don't need to "unbox" the Proxy-object to get the type return lazyInitialiser.PersistentClass; } return entity.GetType();
首先检查代理服务器后面的types是否抽象,并使用Vijay或Diego的方法,具体取决于具体types是否已知。
换句话说,如果代理之后的types不是一个具体types,或者可能是一个子types,它只会加载对象。
我做了一个快速的unit testing来certificate这是有效的,但是我不认为我已经testing了所有可能的情况 – 我相信这个想法是正确的,但是我想听听Diego和Vijay或者其他人的意见。
谢谢!
编辑:发布上述要点的更新,用一个额外的通用方法,可用于Unproxy()一个实体 – 有些情况下,你可能必须这样做…