Как захватить трассировку стека из другой точки кода, как внутреннее исключение? - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть этот фрагмент C #:

public class Program
{
    static void Main(string[] args)
    {
        try
        {
            var ty = new Thready();
            ty.Culprit();
            ty.Scapegoat();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            return;
        }
    }
}

public class Thready
{
    string state;
    Exception moreInfoException;

    void Scapegoat()
    {
        if (state != "Correct State")
            throw new Exception("You called me at the wrong state!", moreInfoException);
    }

    void Culprit()
    {
        state = "Wrong State";
        moreInfoException = new Exception("Here's when YOU changed the state!");
    }
}

Он печатает это (обратите внимание на отсутствующий след из исключения Culprit):

System.Exception: You called me at the wrong state! ---> System.Exception: Here's when YOU changed the state!
   --- End of inner exception stack trace ---
   at MyApp.Thready.Scapegoat() in C:\src\MyApp\Program.cs:line 142
   at MyApp.Program.Main(String[] args) in C:\src\MyApp\Program.cs:line 20

Вот одно из решений:

public class Thready
{
    string state;
    private ExceptionDispatchInfo captured;

    public void Scapegoat()
    {
        if (state != "Correct State")
        {
            try
            {
                captured.Throw();
            }
            catch (Exception ex)
            {
                throw new Exception("You called me at the wrong state!", ex);
            }
        }
    }

    public void Culprit()
    {
        state = "Wrong State";
        try
        {
            throw new Exception("Here's when YOU changed the state!");
        }
        catch (Exception ex)
        {
            captured = ExceptionDispatchInfo.Capture(ex);
        }
    }
}    

Он печатает правильный след:

System.Exception: You called me at the wrong state! ---> System.Exception: Here's when YOU changed the state!
   at MyApp.Thready.Culprit() in C:\src\MyApp\Program.cs:line 57
--- End of stack trace from previous location where exception was thrown ---
   at MyApp.Thready.Scapegoat() in C:\src\MyApp\Program.cs:line 43
   --- End of inner exception stack trace ---
   at MyApp.Thready.Scapegoat() in C:\src\MyApp\Program.cs:line 47
   at MyApp.Program.Main(String[] args) in C:\src\MyApp\Program.cs:line 22

Однако для этого требуется, чтобы я сгенерировал исключение, перехватил его и вызвал метод Capture() в Culprit. А затем в Scapegoat мне нужно позвонить Throw(), снова поймать и заключить в последнее исключение. Это выглядит медленно.

Существует ли более быстрое и менее бюрократическое / многословное решение?

...