在NHibernate对象上使用动态代理

时间:2009-10-19 10:04:31

标签: c# nhibernate proxy castle-dynamicproxy dynamic-proxy

我正在尝试使用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 IInterceptor:

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

使用Castle.DynamicProxy2创建Pet类的审计实例非常简单。

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

现在问题来了。由于Pet是持久化的,系统需要处理通过NHibernate获取的Pet的实例。我想要发生的是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>)。我正在尝试清理的现有系统广泛使用它们。

所以我希望是否有人有任何解决方法或任何有关我正在做什么的见解是明智的。

万分感谢,

卡洛斯

2 个答案:

答案 0 :(得分:3)

您可以使用NHibernate Event Listeners

这些挂钩到NHibernate的事件系统并拦截这样的动作。这可能比使用代理更好,因为明显的运行时创建代理性能增益。

该链接实际上显示了审核应用示例。

答案 1 :(得分:0)

看看this post。作者在NHibernate中使用ProxyFactoryFactory(nice name =))的概念来实现实体类的自定义代理。

可以设置ProxyFactoryFactory类型through configuration或代码。

也许这会解决你的任务。