Не уверены в поведении «есть» с прокси nHibernate - PullRequest
1 голос
/ 15 июля 2011

У меня есть ситуация, когда мне нужно определить, является ли унаследованный класс конкретным унаследованным классом, но тип, ожидаемый в модели, является базовым классом, и он сохраняется с использованием nHibernate / Fluent nHibernate с использованиемTable Per Concrete Class Иерархия.Так что моя структура выглядит примерно так ...

class Mutation : Entity {
   virtual Aspect Aspect { get; set; }
   virtual Measurement Measurement { get; set; }
}

abstract class Measurement : Entity {
   // does nothing on its own, really.
}

class Numeric : Measurement {
   virtual int Value { get; set; }
   // may have some other properties
}

class Observable : Measurement {
  virtual Aspect Aspect { get; set; }
}

Итак, вот что здесь происходит.Mutation предполагает указание на тип данных и измеренное изменение (могут быть другие способы изменения данных, а не только плоские числа).И тогда у меня будет объект, который просто ожидает IList<Mutation> и сопоставит каждый последующий тип Measurement с его собственной конкретной таблицей, разделяющей Identity с базовым классом Measurement.Пока это прекрасно работает.

Теперь Observable отличается тем, что он не хранит свое собственное значение, а скорее снова указывает на другой Aspect, который может иметь свой собственный набор мутаций и изменений.Идея состоит в том, что значение всегда будет извлекаться из предполагаемого источника, а не сохраняться как плоское значение в базе данных.(Есть причина желать такого поведения, которое выходит за рамки этого вопроса)

Итак, моя мысль заключалась в том, чтобы поставить такую ​​оценку, как эта ..

foreach(var measurement in list) {
   if(measurement is Observable){
      // then we know to lookup the other value
   }
}

Этоне работалЯ все еще получаю результат прокси всего MeasurementProxy.Но тот же код прекрасно работает в автономном C# приложении без использования nHibernate, поэтому я чувствую большую уверенность в том, что проблема связана с прокси.

Затем я добавил следующий метод в свою базуEntity класс ...

        /// <summary>
        /// Unwrap the type from whatever proxy it may be
        /// behind, returning the actual .NET <typeparamref name="System.Type"/>.
        /// </summary>
        /// <returns>
        /// A pure <typeparamref name="System.Type"/> that is no longer proxied.
        /// </returns>
        public virtual Type Unwrap() {
            return GetType();
        } 

Теперь, если я делаю Console.WriteLine(measurement.Unwrap());, я получаю правильный тип, но та же оценка ...

foreach(var measurement in list) {
   if(measurement.Unwrap() is Observable){
      // then we know to lookup the other value
   }
}

все еще не работает,Это никогда не работает.Может ли кто-нибудь помочь мне здесь?

Ответы [ 2 ]

2 голосов
/ 15 июля 2011

Это потому что Unwrap() возвращает Type, поэтому measurement.Unwrap() is Observable всегда будет false, а measurement.Unwrap() is Type всегда будет true.

Используйте typeof оператор и равенство ссылок вместо:

if (measurement.Unwrap() == typeof(Observable)) {
    // Then we know to lookup the other value.
}
0 голосов
/ 23 августа 2013

Проверка в ответе Хамиди не достаточна.Как только вы добавите некоторые ленивые свойства в ваше отображение, например:

<property name="Description" type="StringClob" not-null="false" lazy="true"/>

, метод Unwrap завершится неудачно, потому что для типов, которые используют ленивые свойства, объекты всегда прокси и проверка

if (measurement.Unwrap() == typeof(Observable)) {
    // Then we know to lookup the other value.
} 

не удастся, потому что Unwrap вернет тип прокси, а не ожидаемый тип.

Я использую следующие методы для проверки типов сущностей:

public virtual Type GetEntityType()
{
    var type = GetType();
    // Hack to avoid problem with some types that always be proxy. 
    // Need re-evaluate when upgrade to NH 3.3.3
    return type.Name.EndsWith("Proxy") ? type.BaseType : type;
}

public virtual bool IsOfType<T>()
{
    return typeof(T).IsAssignableFrom(GetEntityType());
}

и проверкастановится:

if (measurement.IsOfType<Observable>()) {
    // Then we know to lookup the other value.
}

Как вы видите в комментарии к коду, это хак для NH 3.1 и Castle Proxy: типы Castle Dynamic Proxy всегда заканчиваются Proxy, поэтому я использовал эту сигнатуру, чтобы определить, является ли объектпрокси или нет.Мой проект все еще застрял с NH3.1, поэтому я не уверен, какие изменения понадобятся методу с NH3.3.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...