1

我有一个旧的 MonoRail/ActiveRecord 我也一直在做一些工作。

最近我决定将应用程序升级到 Castle Trunk & NHibernate 2.1.0.4000 GA,现在我发现运行测试存在一些问题:

首先 - 当使用 TestDriven.Net 运行针对数据库的集成测试时,它会使 TestDriven.Net 完全崩溃,或者所有测试都完成执行,然后 TestDriven.Net 挂起。这在升级之前从未发生过。

当 TestDriven.Net 崩溃时,写入事件日志的内容如下:

故障桶 1467169527,类型 1 事件名称:APPCRASH 响应:不可用 Cab Id:0

问题签名:P1:ProcessInvocation86.exe P2:2.22.2468.0 P3:4a26845c P4:KERNELBASE.dll P5:6.1.7600.16385 P6:4a5bdbdf P7:e053534f P8:0000b727 P9:P10:

第二件事 - 当代理类被 Finalize()'d 时,正在记录异常,如下所示 - 似乎一旦记录了几次,即 TestDriven.Net 崩溃时。

这是异常的堆栈跟踪:

NHibernate.LazyInitializationException:     
Initializing[MyApp.Core.Models.TestExecutionPackage#15d9eb96-faf0-4b4b-9c5c-9cd400065430]-Could not initialize proxy - no Session.
  at NHibernate.Proxy.AbstractLazyInitializer.Initialize()
  at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation()
  at NHibernate.ByteCode.Castle.LazyInitializer.Intercept(IInvocation invocation)
  at Castle.DynamicProxy.AbstractInvocation.Proceed()
  at Castle.Proxies.TestExecutionPackageProxy.Finalize()

同样的行为也会使我们的 CI 服务器上的 MsBuild 崩溃。

真正奇怪的是,理论上 Finalize() 中抛出的异常应该按照 MSDN 文档被吞掉:

http://msdn.microsoft.com/en-us/library/system.object.finalize(VS.71).aspx

如果Finalize或Finalize的覆盖引发异常,运行时将忽略该异常,终止该Finalize方法,并继续完成过程。

有人想吗?

4

2 回答 2

0

从来没有完全了解这个问题,但我最终通过创建自己的 LazyInitializer 实现实现了一个相当基本的工作,我在调用时检查 Finalize 方法,如下所示:

/// <summary>
/// Invoke the actual Property/Method using the Proxy or instantiate the actual
/// object and use it when the Proxy can't handle the method. 
/// </summary>
/// <param name="invocation">The <see cref="IInvocation"/> from the generated Castle.DynamicProxy.</param>
public virtual void Intercept(IInvocation invocation)
{
  try
  {
    if (invocation.Method.Name == "Finalize")
    {
      return;
    }
    if (_constructed)
    {
      // let the generic LazyInitializer figure out if this can be handled
      // with the proxy or if the real class needs to be initialized
      invocation.ReturnValue = base.Invoke(invocation.Method, invocation.Arguments, invocation.Proxy);

      // the base LazyInitializer could not handle it so we need to Invoke
      // the method/property against the real class
      if (invocation.ReturnValue == InvokeImplementation)
      {
        invocation.ReturnValue = invocation.Method.Invoke(GetImplementation(), invocation.Arguments);
        return;
      }
      else
      {
        return;
      }
    }
    else
    {
      // TODO: Find out equivalent to CGLIB's 'method.invokeSuper'.
      return;
    }
  }
  catch (TargetInvocationException tie)
  {
    // Propagate the inner exception so that the proxy throws the same exception as
    // the real object would 
    Exception_InternalPreserveStackTrace.Invoke(tie.InnerException, new Object[] { });
    throw tie.InnerException;
  }
}
于 2009-12-03T04:03:19.663 回答
0

当我迁移到 NHibernate 的 2.1.2 版本时,我遇到了同样的问题。我已经为 LinFu Proxy 更改了 Castle,然后一切对我来说都很好。希望这可以帮助。

于 2010-08-02T19:08:16.273 回答