等于实现NHibernate Entities,unproxy问题

Can*_*cer 12 .net c# nhibernate

在NHibernate 3.0 Cookbook中,有一个基本实体类型的示例实现.equals实现如下:

public abstract class Entity<TId>
{
  public virtual TId Id { get; protected set; }

  public override bool Equals(object obj)
  {
    return Equals(obj as Entity<TId>);
  }

  private static bool IsTransient(Entity<TId> obj)
  {
     return obj != null && Equals(obj.Id, default(TId));
  }  

  private Type GetUnproxiedType()
  {
     return GetType();
  }  

  public virtual bool Equals(Entity<TId> other)
  {
    if (other == null) return false;            
    if (ReferenceEquals(this, other)) return true;

    if (!IsTransient(this) && !IsTransient(this) && Equals(Id, other.Id))
    {
      var otherType = other.GetUnproxiedType();
      var thisType = GetUnproxiedType();
      return thisType.IsAssignableFrom(otherType) ||
         otherType.IsAssignableFrom(thisType);
    }
    return false;
  }    
}
Run Code Online (Sandbox Code Playgroud)

GetUnproxiedType()方法的原因是:有一个抽象基类Product,一个继承自Product的具体类Book和一个由NHibernate用于延迟加载的动态代理类ProductProxy.如果表示书籍和具体书籍的ProductProxy具有相同的ID,则应将它们视为相等.但是我真的不明白为什么在这个案例中调用ProductProxy实例上的GetType()应该返回Product,以及它如何帮助.有任何想法吗?

Can*_*cer 7

我实际上继续写信给这本书的作者关于这段代码.事实证明这是由于代理包装的工作原理.以下是他的回答:

"如果你不理解代理框架是如何工作的,那么这个想法看起来很神奇.

当NHibernate为延迟加载返回代理时,它返回从实际类型继承的代理实例.我们可以访问一些成员,而无需强制从数据库加载.其中包括代理的Id属性或字段,GetType()在某些情况下Equals()GetHashCode().访问任何其他成员将强制从数据库加载.

发生这种情况时,代理会创建一个内部实例.因此,例如,一个延迟加载的Customer(CustomerProxy102987098721340978)实例,在加载时,将在内部创建一个Customer包含数据库中所有数据的新实例.代理然后做这样的事情:

public overrides string Name 
{ 
    get { 
       return _loadedInstance.Name; 
    } 
    set { _loadedInstance.Name = value; } 
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,正是这个重写要求所有内容都是允许延迟加载的实体上的虚拟内容.

因此,对代理上的Name属性的所有调用都将中继到Customer具有实际数据的内部实例.

GetUnproxiedType()利用这一点.GetType()对代理的简单调用将返回typeof(CustomerProxy02139487509812340).呼叫GetUnproxiedType()将被转发到内部客户实例,内部客户实例将返回typeof(Customer)."