开发者

How to create predictable output with a Lazy<StackFrame>

开发者 https://www.devze.com 2023-01-31 14:46 出处:网络
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 m开发者_运

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 m开发者_运维技巧y 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.


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++);
    }
    //...
}
0

精彩评论

暂无评论...
验证码 换一张
取 消