Проксирование объектов NHibernate с помощью Castle DynamicProxy использует NH-функциональность

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

  • Используйте 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;
}

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

    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 выполняются), но это вообще ничего не меняет.

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

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


person Sebastian Edelmeier    schedule 27.03.2012    source источник


Ответы (1)


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

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

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

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

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

person Sebastian Edelmeier    schedule 27.03.2012