代码之家  ›  专栏  ›  技术社区  ›  Marc Gravell

识别NHibernate代理类

  •  37
  • Marc Gravell  · 技术社区  · 16 年前

    代码不会预先知道NHibernate(包括没有参考,但我不需要反思-(p)

    DataContractSerializer [attribute] 装饰。

    7 回复  |  直到 16 年前
        1
  •  49
  •   Diego Mijelshon    15 年前

    INHibernateProxy .

    如果需要获取底层的“真实”对象,请使用:

    Session.GetSessionImplementation().PersistenceContext.Unproxy(proxiedObject)
    

    您不需要测试要调用的代理 Unproxy ; 如果不是代理,则返回原始参数。

    编辑: 我现在使用一种不同的方法来获取底层对象,主要是针对延迟加载和继承: http://sessionfactory.blogspot.com/2010/08/hacking-lazy-loaded-inheritance.html

        2
  •  17
  •   Vijay Patel    16 年前

    我猜你不是真的想访问实际的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();
        }
    }
    

    希望有帮助。

        3
  •  8
  •   Samuel Poirier    13 年前

    var realType = NHibernate.NHibernateUtil.GetClass(proxyInstance);
    

    希望这有帮助:D

        4
  •  1
  •   s1mm0t    16 年前

    NHibernate在运行时创建(代理)原始实体的子类,以便能够进行延迟加载。它只能这样做,因为您被迫将所有属性标记为“虚拟”。我想不出你怎么能发现一个对象是一个代理,而不是任何其他类型的子分类-当然不是在一个通用的方式。我只能假设您的代码在这种情况下引发了异常,因为正在(反)序列化的实际类没有标记为可序列化。我认为您唯一能做的就是放宽验证,或者如果子类重写其基类的所有属性,则允许对其进行序列化。

    反序列化为原始类型就可以了。

        5
  •  1
  •   Jamie Ide    16 年前

    nhibernate2.1+允许通过配置设置动态代理提供程序。我知道的实现有Castle(默认)、LinFu和Spring。NHibernate不需要接口或属性。我认为这使得很难可靠地检测对象是否是代理。

    正如s1mm0t所回答的,在反序列化时创建实际的类型是可以的。

        6
  •  1
  •   Jordão    15 年前

        7
  •  1
  •   mindplay.dk    14 年前

    Diego的方法在尝试确定对象的类型之前完全加载对象—这绝对是最通用的方法,但是如果代理已经知道具体类型,则可能不需要加载对象。

    Vijay的方法在预先知道具体类型的情况下更快——但正如Diego所指出的,在某些情况下,这种信息是不可用的,因为确定确切类型所需的信息尚未加载。

    考虑到这两种情况,我得出以下结论:

    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();
    

    换句话说,它只在代理后面的类型不是具体类型或者可能是子类型时加载对象。

    编辑:发布了对上述要点的更新,并提供了一个附加的泛型方法,可用于取消实体的xy()-在某些情况下,您可能必须这样做。。。

    推荐文章