Я пытаюсь использовать 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>
). Существующая система, которую я пытаюсь очистить, широко использует их.
Поэтому я надеюсь, что у кого-нибудь есть обходной путь или какое-либо понимание того, целесообразно ли то, что я делаю.
Бесконечно благодарен,
Карлос