3

我正在尝试使用 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();

whereProxyHelper.GetProxyType<Pet>()将返回缓存的 Pet 代理类型。主要缺点是该解决方案不适用于通用列表(例如IList<Pet>)。我正在尝试清理的现有系统广泛使用它们。

因此,我希望是否有人对我正在做的事情是否可取有任何解决方法或任何见解。

太感谢了,

卡洛斯

4

2 回答 2

3

您可以使用NHibernate Event Listeners

这些挂钩到 NHibernate 的事件系统并拦截此类操作。由于明显的运行时创建代理性能提升,这甚至可能比使用代理更好。

该链接实际上显示了一个审核应用程序示例。

于 2009-10-19T13:43:04.750 回答
0

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

可以通过配置或代码设置 ProxyFactoryFactory 类型。

也许这会解决你的任务。

于 2009-10-19T10:25:27.400 回答