我为NHibernate使用的所有业务对象都有一个基类DomainObject
。它包含Id
属性。
public abstract class DomainObject
{
public virtual int Id { get; private set; }
}
我想写一个IEqualityComparer
来比较我的域对象。如果两个对象具有相同的Id
并且是相同类型的对象,则它们应该相等。但是,当我使用GetType()
获取对象的类型时,它将返回NHibernate代理类型。所以这段代码:
bool IEqualityComparer.Equals(object x, object y)
{
// null checking code skipped here
if(x is DomainObject && y is DomainObject)
{
return ((DomainObject) x).Id == ((DomainObject) y).Id
&& x.GetType() == y.GetType();
}
return x.Equals(y);
}
无效,因为x is Asset
的类型,但y is AssetProxy21879bba3e9e47edbbdc2a546445c657
的类型。
那么,如何在可能是NHibernate代理对象的对象上获取实体类型?即在上面的示例中Asset
而不是AssetProxy21879bba3e9e47edbbdc2a546445c657
?
答案 0 :(得分:22)
您可以通过以下方式获取代理的真实类型:
NHibernateUtil.GetClass(x);
或者您可以向DomainObject
添加方法,例如:
public virtual Type GetTypeUnproxied()
{
return GetType();
}
这很光滑,不直接依赖于NHibernate。
或者,可以通过说你需要获得真正的对象而不是代理来解决问题,如果会话很方便,可以使用:
session.PersistenceContext.Unproxy(x);
正如另一个答案中所提到的,如果你想要实现平等,最好查看Sharp architecture implementation of Equals。
答案 1 :(得分:2)
要获取真实对象而不是代理,您可以使用
session.PersistenceContext.Unproxy(proxyObject)
但我认为你应该看看Sharp architecture implementation等于Equals。
答案 2 :(得分:0)
您可以按照here所述实现后门属性,以获取实际的非代理实例。
答案 3 :(得分:-1)
我在生产项目中采用了不同的方法。我只需要一个全局的HiLow Id-Generator,它可以为所有类型生成唯一的Ids:
// in DomainEntity
public override bool Equals(object obj)
{
var other = obj as DomainEntity;
if (Id == 0) // IsTransient()
return ReferenceEquals(this, other);
else
return (other != null) && (Id == other.Id);
}
// Comparer
bool IEqualityComparer.Equals(object x, object y)
{
return object.Equals(x, y);
}