Как получить тип объекта на объекте, который может быть прокси-объектом NHibernate?
У меня есть базовый класс DomainObject
для всех моих бизнес-объектов, которые я использую с NHibernate. Он содержит свойство 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
?
Ответы
Ответ 1
Вы можете получить реальный тип прокси с помощью:
NHibernateUtil.GetClass(x);
или вы можете добавить метод к DomainObject
, например:
public virtual Type GetTypeUnproxied()
{
return GetType();
}
Это действительно гладкий и не зависит напрямую от NHibernate.
В качестве альтернативы можно подойти к проблеме, указав, что вам нужно получить истинный объект, а не прокси-сервер, который, если сеанс удобен, может быть выполнен с помощью:
session.PersistenceContext.Unproxy(x);
Как уже упоминалось в другом ответе, если вы пытаетесь реализовать равные, было бы неплохо проверить реализацию архитектуры Sharp Equals.
Ответ 2
Чтобы получить реальный объект вместо прокси-сервера, вы можете использовать
session.PersistenceContext.Unproxy(proxyObject)
Но я думаю, вам стоит взглянуть на Реализация архитектуры Sharp для Equals.
Ответ 3
Вы можете реализовать свойство backdoor, как описано здесь, чтобы получить фактический непроксированный экземпляр.
Ответ 4
Я принял другой подход в производственном проекте. У меня просто есть глобальный IdL генератор HiLow, который генерирует Id, уникальный для всех типов, и я могу:
// 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);
}