识别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()一个实体 – 有些情况下,你可能必须这样做…