首页 > 解决方案 > 如何在给定时间保持对对象状态的引用?

问题描述

我的目标是在引发异常时将调用堆栈状态保存在文件中。但是我有一个主要的限制:我不能触及任何现有的代码。我的目标是在我不知道当前工作流程的情况下实现它。所以我可以在任何 C# 项目中使用它。

为此,我需要访问导致异常的所有嵌套方法以及所有方法的参数。

到目前为止,我使用 postsharp OnMethodBoundaryAspect,它允许我定义 OnEntry、OnSucess 和 OnException 方法,这些方法在输入、返回或引发异常时调用。很棒的是我可以postsharp.config在我想要的项目中应用这个方面的文件。没有源代码修改,我只是将我的项目添加到解决方案中,一个配置文件,并在解决方案的每个项目中引用我的项目,我很高兴。使用它我可以维护自己的调用堆栈,并且可以保存对方法名称的引用和对方法参数的引用。

现在让我们说 amethodA调用 amethodB哪个调用 a methodC

我所做的工作很好,除了显然我使用参考。因此,如果在引发异常之前methodA修改了参数,当我序列化调用堆栈时,我们将看到一个调用堆栈,其中有一个错误值的参数(我们将看到在 中设置的值)。methodCmethodAmethodC

我想解决这个问题,我考虑使用:

  1. 在 OnEntry 方法中进行深度克隆以复制所有方法参数,但这会导致糟糕的性能
  2. PostSharp LocationInterceptorAspect 但这需要付费许可证
  3. VEH Hooking,但速度非常慢,使用起来可能会更快deepcloning

有没有其他方法可以让我及时保存对象的状态,并且性能优于deepcloning,或者至少让我拦截对指定对象的所有修改(如 VEH 挂钩或 LocationInterceptor Aspect)?

PS:我不能使用IOnPropertyChange或类似的东西,因为我不能触及任何现有的源代码,除非我可以在运行时实现它们,但我没有看到任何可能的地方。

标签: c#callstack

解决方案


考虑到我不想在需要监控的对象中实现任何特定代码,我只有 2 个选项:

  1. 需要保存状态时的序列化或任何深度克隆方法(我在此解决方案中使用了 JSON.NET)

  2. 记录对对象的所有修改,以便在必要时撤消它们 => 以便在发生修改时得到通知我探索了所有这些技术:

    • 带有LocationInterceptionAspect的 Postsharp (不是免费的)
    • Harmony 2允许拦截任何函数调用(在我的情况下是属性的 setter 函数),如果您可以丢弃任何字段更改,这是最简单和最简单的工作解决方案
    • VEH 挂钩,理论上可行,但速度极慢,由于其复杂性,我没有进行太多探索
    • 编辑函数的 MSIL 代码以挂钩所有stfld指令。

推荐阅读