如何使用 Lazy创建可预测的输出

发布于 2024-10-08 13:25:25 字数 1151 浏览 7 评论 0原文

我正在开发一些内部日志框架,为了性能的考虑,惰性地获取一个 StackFrame 似乎是个好主意。我想使用这个 StackFrame 来获取日志框架之外的第一个方法。

我最初的想法是这样的:

using System;
using System.Diagnostics;
using NUnit.Framework;

[TestFixture]
public class Test
{
    [Test]
    public void Caller()
    {
        NeedsToNowCaller();
    }

    public void NeedsToNowCaller()
    {
        Processor.GetName(() => new StackFrame(4));

        Really();
        Assert.AreEqual("Caller", Processor.stackFrame.Value.GetMethod().Name);
    }

    public void Really()
    {
        Assert.AreEqual("Caller",Processor.stackFrame.Value.GetMethod().Name);
    }
}

public static class Processor
{
    public static Lazy<StackFrame> stackFrame;

    public static void GetName(Func<StackFrame> stackFrameProvider)
    {
        stackFrame = new Lazy<StackFrame>(stackFrameProvider);
    }
}

但是当你交换这些行时:

    Really();
    Assert.AreEqual("Caller", Processor.stackFrame.Value.GetMethod().Name);

结果是不可预测的,因为调用堆栈发生了变化。无论如何,是否可以通过闭包获得本地作用域/框架的钩子,同时保留惰性。

我能想到的唯一解决方案是逐步执行 StackTrace,直到我使用未知方法检测到第一帧。

我真的希望有更好的解决方案。

I'm working on some internal logging framework and for the sake of performance it seems a good idea to lazily get a StackFrame. I want to use this StackFrame to get the first method outside my logging framework.

My initial idea was this:

using System;
using System.Diagnostics;
using NUnit.Framework;

[TestFixture]
public class Test
{
    [Test]
    public void Caller()
    {
        NeedsToNowCaller();
    }

    public void NeedsToNowCaller()
    {
        Processor.GetName(() => new StackFrame(4));

        Really();
        Assert.AreEqual("Caller", Processor.stackFrame.Value.GetMethod().Name);
    }

    public void Really()
    {
        Assert.AreEqual("Caller",Processor.stackFrame.Value.GetMethod().Name);
    }
}

public static class Processor
{
    public static Lazy<StackFrame> stackFrame;

    public static void GetName(Func<StackFrame> stackFrameProvider)
    {
        stackFrame = new Lazy<StackFrame>(stackFrameProvider);
    }
}

But when you swap these lines:

    Really();
    Assert.AreEqual("Caller", Processor.stackFrame.Value.GetMethod().Name);

Results are unpredictable, since the call stack is changed. Is there anyway to get a hook to the local scope/frame through a closure, while retaining the laziness.

The only solution i can think of is stepping through the StackTrace, until i detect the first frame with a unknown method.

I really hope there's a better solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

东北女汉子 2024-10-15 13:25:25

我不知道这是否好得多,但与其寻找未知的方法,不如寻找不同的源类可能更简单。这有点粗糙,但是像这样的东西会在进入日志记录类之前为您提供最后一帧,而不必维护“已知”方法名称列表(假设日志记录方法不是静态的......)?

public void DoStuff()
{
    int index = 0;
    StackFrame frame = new StackFrame(index++);
    while (this.GetType().Name.Equals(frame.GetMethod().DeclaringType.Name))
    {
        frame = new StackFrame(index++);
    }
    //...
}

I don't know that this is much better, but instead of looking for an unknown method, it might be simpler to look for a different source class. This is a bit rough, but would something like this work to give you the last frame before entering the logging class without having to maintain a list of "known" method names (assuming the logging method is not a static...)?

public void DoStuff()
{
    int index = 0;
    StackFrame frame = new StackFrame(index++);
    while (this.GetType().Name.Equals(frame.GetMethod().DeclaringType.Name))
    {
        frame = new StackFrame(index++);
    }
    //...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文