【问题标题】:Proxying NHibernate Objects with Castle DynamicProxy swallows NH-Functionality使用 Castle DynamicProxy 代理 NHibernate 对象会吞噬 NH-Functionality
【发布时间】:2012-04-10 19:00:10
【问题描述】:

我最近在做一些被一些人认为很可怕的事情,但我个人很喜欢这种实验。这是电报样式的描述:

  • 使用 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;
}

使用的拦截器定义如下:

    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 的环境中可以正常工作(在代码中创建对象,其中 Object 拥有自己的数据)。 不幸的是,Intercept 方法中的else 部分似乎使NHibernate 无法正常工作,似乎_wrappedObject 被简化为它的基本类型功能(而不是被NHibernate 代理),因此所有映射的子集合都保持为空。

我尝试从 lazy 切换到 eager 加载(并确认所有 SQL 都已执行),但这并没有改变任何东西。

有人知道我可以做些什么来让它恢复工作吗?

提前非常感谢!

【问题讨论】:

    标签: nhibernate proxy interceptor castle-dynamicproxy


    【解决方案1】:

    我发现我所做的部分是错误的,部分是不完整的。我没有删除这个问题,而是选择自己回答,以便其他人也能从中受益。

    首先,我将类代理误解为实例代理,这就是我存储_wrappedObject 的原因。我需要对象来执行invocation.Method.Invoke(_wrappedObject, invocation.Arguments),这是下一个错误。我不应该这样做,而是应该使用invocation.Proceed() 将调用传递给下一个拦截器。

    现在,不完整在哪里? NH 似乎需要了解有关它的实例的元数据,所以我错过了一条重要的线来让 NH 意识到代理是它的亲属之一:

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

    这仅适用于 NHibernate 拦截器,因此最终产品与我最初的产品略有不同...废话太多了,您可以在 Ayende 的 website 上看到一个非常易于理解的示例。他的精彩教程的大道具!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多