Проксирование объектов NHibernate с помощью Castle DynamicProxy поглощает функциональность NH - PullRequest
0 голосов
/ 27 марта 2012

В последнее время я делаю вещи, которые некоторые считают ужасными, но мне лично нравится такой эксперимент. Вот описание стиля телеграфа:

  • Использование NH для извлечения объектов данных
  • Каждый объект DataObject упакован в CastleDynamicProxy
  • Когда запрашиваются свойства, оформленные с помощью пользовательских атрибутов, перенаправьте их на собственный код вместо NHibernate, чтобы получить значение возврата.

Создание объекта / код извлечения данных

Objects=GetAll().Select(x=>ProxyFactory.CreateProxy<T>(x)).ToList();

public IList<Person> GetAll()
{
    ISession session = SessionService.GetSession();
    IList<Person> personen = session.CreateCriteria(typeof(Person))
                          .List<Person>();
    return personen;
}

Код генерации прокси:

public T CreateProxy<T>(T inputObject)
{
    T proxy = (T)_proxyGenerator.CreateClassProxy(typeof(T), new ObjectRelationInterceptor<T>(inputObject));
    return proxy;
}

Используемый перехватчик определяется следующим образом:

    public class MyInterceptor<T> : IInterceptor
    {
        private readonly T _wrappedObject;

        public MyInterceptor(T wrappedObject)
        {
            _wrappedObject = wrappedObject;
        }

        public void Intercept(IInvocation invocation)
        {
            if (ShouldIntercept(invocation)) { /* Fetch Data from other source*/ }
            else
            {
                invocation.ReturnValue = invocation.Method.Invoke(_wrappedObject, invocation.Arguments);
            }
        }


        public bool ShouldIntercept(IInvocation invocation)
        {
            // true if Getter / Setter and Property
            // has a certain custom attribute
        }
    }

Это прекрасно работает в среде без NHibernate (создание объектов в коде, где объект хранит свои собственные данные). К сожалению, часть else в методе Intercept, кажется, оставляет NHibernate неработоспособным, кажется, что _wrappedObject сокращен до функциональности базового типа (вместо того, чтобы быть проксируемым NHibernate), поэтому все сопоставленные дочерние коллекции остаются пустыми.

Я попытался переключиться с lazy на eager загрузку (и подтвердил, что весь SQL выполняется), но это ничего не меняет.

Кто-нибудь знает, что я могу сделать, чтобы вернуть это к работе?

Заранее большое спасибо!

1 Ответ

1 голос
/ 27 марта 2012

Я обнаружил, что то, что я делаю, частично неправильно и частично неполно. Вместо того, чтобы удалить этот вопрос, я решил ответить на него сам, чтобы другие тоже могли извлечь из него пользу.

Прежде всего, я неправильно понял, что прокси класса является прокси экземпляра, поэтому я и сохранил _wrappedObject. Мне нужно, чтобы Объект выполнил invocation.Method.Invoke(_wrappedObject, invocation.Arguments), что является следующей ошибкой. Вместо этого я должен был передать вызов следующему перехватчику, используя invocation.Proceed().

Теперь, где был этот незавершенный? NH, похоже, должен знать метаданные об их экземплярах, поэтому я пропустил одну важную строку, чтобы NH знал, что прокси - один из его родственников:

SessionFactory.GetClassMetadata(entityName).SetIdentifier(instance, id, entityMode);

Это работает только в NHibernate Interceptor, так что конечный продукт немного отличается от моего первоначального ... Достаточно бред, вы можете увидеть очень очень понятный пример этого на сайте Ayende . Большие реквизиты для его великолепного урока!

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