Использование динамического прокси для объектов NHibernate

Я пытаюсь использовать Castle.DynamicProxy2 для очистки кода в сохраненных классах NHibernate. Вот простая версия.

Класс питомца:

public class Pet
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

И его файл сопоставления:

<class name="Pet" table="Pet">
  <id name="Id" column="Id" unsaved-value="0">
    <generator class="native"/>
  </id>
  <property name="Name" column="Name"/>
  <property name="Age" column="Age"/>
</class>

Необходим аудит экземпляров класса Pet. Обычно свойства Name и Age не являются автоматическими свойствами и содержат логику для записи изменений значений. Теперь я думаю об использовании прокси для внедрения логики аудита в установщики свойств. Для этого я создал перехватчик Auditor II:

public class Auditor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // Do something to record changes
        invocation.Proceed();
    }
}

Достаточно просто создать проверенный экземпляр класса Pet с помощью Castle.DynamicProxy2.

Pet aPet = proxyGenerator.CreateClassProxy<Pet>(new Auditor());
aPet.Name = "Muffles"; // The Auditor instance would record this.
aPet.Age = 4;          // and this too...

Вот и проблема. Поскольку Pet сохраняется, системе необходимо будет работать с экземплярами Pet, полученными через NHibernate. Я хочу, чтобы NHibernate автоматически возвращал экземпляры прокси-сервера Pet следующим образом:

// I would imagine an instance of Auditor being created implicitly
ICriteria criteria = session.CreateCriteria(typeof(Pet));
criteria.Add(Expression.Expression.Eq("Name", "Muffles"));

// return a list of Pet proxies instead
// so changes can be recorded.
IList<Pet> result = criteria.List<Pet>();

Pet aPet = result[0];
aPet.Age = aPet.Age + 1;

// I expect this to succeed since the proxy is still a Pet instance
session.Save(aPet); 

Я придумал что-то вроде этого, чтобы обойти это:

ICriteria criteria = session.CreateCriteria(ProxyHelper.GetProxyType<Pet>());
criteria.Add(Expression.Expression.Eq("Name", "Muffles"));

// use List() instead of List<T>()
// and IList instead of IList<Pet>
IList results = criteria.List();

где ProxyHelper.GetProxyType<Pet>() вернет кэшированный тип прокси Pet. Основным недостатком является то, что это решение не будет работать с общими списками (например, IList<Pet>). Существующая система, которую я пытаюсь очистить, широко использует их.

Поэтому я надеюсь, что у кого-нибудь есть обходной путь или какое-либо понимание того, целесообразно ли то, что я делаю.

Бесконечно благодарен,

Карлос


person ca7l0s    schedule 19.10.2009    source источник


Ответы (2)


Вы можете использовать прослушиватели событий NHibernate .

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

Ссылка на самом деле показывает пример приложения аудита.

person NT_    schedule 19.10.2009
comment
+1 Аудит, кажется, является дополнительной ответственностью класса сущности. - person Aaron Fischer; 20.10.2009

Прочтите этот пост. Автор использует понятие ProxyFactoryFactory (nice name =)) в NHibernate для реализации настраиваемых прокси для классов сущностей.

можно установить тип ProxyFactoryFactory через конфигурацию или в коде.

Может, это решит вашу задачу.

person elder_george    schedule 19.10.2009
comment
Я проверил сообщение и, просмотрев ProxyFactoryFactory, наткнулся на ayende.com/Blog/archive/2007/04/17/. Хотя расширение NHibernate для использования моей собственной прокси-фабрики - это здорово, оно будет работать только с ленивыми загруженными классами. Мне все еще нужны прокси-классы, которые загружаются не лениво. - person ca7l0s; 20.10.2009