如何编写捕获异常并删除堆栈跟踪的属性?

发布于 2025-01-02 00:11:31 字数 162 浏览 1 评论 0原文

我希望为函数(或类)编写一个属性,该属性将捕获抛出的任何异常并将其 StackTrace 属性设置为 string.Empty。我该怎么做?

编辑:

如果我无法在普通 C# 中完成此操作,如何使用 PostSharp 在 C# 中完成此操作?

I wish to write an attribute for a function (or class) that will catch any exception thrown and set its StackTrace property to string.Empty. How can I do this?

EDIT:

If I cannot accomplish this in plain C#, how can I do this in C# with PostSharp?

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

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

发布评论

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

评论(2

我纯我任性 2025-01-09 00:11:31
[Serializable] 
public class MyAspect: OnExceptionAspect 
{
    public override void OnException(MethodExecutionArgs args)
    {
       throw new MyCustomException(args.Exception);
    }
} 


public class MyCustomException : Exception
{
    public override string StackTrace
    {
        get
        {
            //return new StackTrace(10).ToString(); //Skip frames
            return string.Empty; //Return empty string
        }
    }
}

您实际上必须抛出一个新的异常。 @Ani 的示例将简单地重新抛出已使用相同堆栈跟踪抛出的异常(由于您如何到达该方面,它是相同的)。引发新的异常将“更改”堆栈跟踪,但不会删除它。如果你想删除它,你将需要抛出你自己的类来覆盖堆栈跟踪属性。将旧异常传递给新异常将使旧异常成为内部异常(如果您想要的话)

您可以使用或不使用 PostSharp 来完成此操作。 关键是您的自定义异常类。

给出以下代码,

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Test1();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace + Environment.NewLine);
        }

        Console.ReadKey();
    }

    private static void Test1()
    {
        try
        {
            Test2();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace + Environment.NewLine);
            throw e;
        }
    }

    private static void Test2()
    {
        try
        {
            Test3();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace + Environment.NewLine);
            throw;
        }
    }

    [MyAspect]
    private static void Test3()
    {
        throw new InvalidOperationException();
    }
}

[Serializable]
public class MyAspect : OnExceptionAspect
{
    public override void OnException(MethodExecutionArgs args)
    {
        throw args.Exception;
    }
}

输出为

在 ConsoleApplication5.MyAspect.OnException(MethodExecutionArgs
args) 在 C:\T est\Program.cs:第 69 行
C:\Test\Program.cs 中的 ConsoleApplication5.Program.Test3():第 59 行
在 C:\Test\Program.cs 中的 ConsoleApplication5.Program.Test2() 处:第 47 行

在 ConsoleApplication5.MyAspect.OnException(MethodExecutionArgs
args) 在 C:\T est\Program.cs:第 69 行
C:\Test\Program.cs 中的 ConsoleApplication5.Program.Test3():第 59 行
在 C:\Test\Program.cs 中的 ConsoleApplication5.Program.Test2() 处:第 52 行
在 C:\Test\Program.cs 中的 ConsoleApplication5.Program.Test1() 处:第 34 行

位于 C:\Test\Program.cs 中的 ConsoleApplication5.Program.Test1():行
39 在 ConsoleApplication5.Program.Main(String[] args) 中
C:\Test\Program.cs:第 19 行

[Serializable] 
public class MyAspect: OnExceptionAspect 
{
    public override void OnException(MethodExecutionArgs args)
    {
       throw new MyCustomException(args.Exception);
    }
} 


public class MyCustomException : Exception
{
    public override string StackTrace
    {
        get
        {
            //return new StackTrace(10).ToString(); //Skip frames
            return string.Empty; //Return empty string
        }
    }
}

You actually have to throw a NEW exception. @Ani's example will simply rethrow the exception already thrown with the same stack trace (it's the same because of how you got to the aspect). Throwing a new exception will "change" the stack trace but it won't erase it. If you want to erase it, you will need to throw your own class that overrides the stack trace property. passing in the old exception to the new exception will make the old exception the inner exception (if you want that)

You can accomplish this with and without PostSharp. The key is your custom exception class.

Given the following code

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Test1();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace + Environment.NewLine);
        }

        Console.ReadKey();
    }

    private static void Test1()
    {
        try
        {
            Test2();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace + Environment.NewLine);
            throw e;
        }
    }

    private static void Test2()
    {
        try
        {
            Test3();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace + Environment.NewLine);
            throw;
        }
    }

    [MyAspect]
    private static void Test3()
    {
        throw new InvalidOperationException();
    }
}

[Serializable]
public class MyAspect : OnExceptionAspect
{
    public override void OnException(MethodExecutionArgs args)
    {
        throw args.Exception;
    }
}

the output is

at ConsoleApplication5.MyAspect.OnException(MethodExecutionArgs
args) in C:\T est\Program.cs:line 69 at
ConsoleApplication5.Program.Test3() in C:\Test\Program.cs:line 59
at ConsoleApplication5.Program.Test2() in C:\Test\Program.cs:line 47

at ConsoleApplication5.MyAspect.OnException(MethodExecutionArgs
args) in C:\T est\Program.cs:line 69 at
ConsoleApplication5.Program.Test3() in C:\Test\Program.cs:line 59
at ConsoleApplication5.Program.Test2() in C:\Test\Program.cs:line 52
at ConsoleApplication5.Program.Test1() in C:\Test\Program.cs:line 34

at ConsoleApplication5.Program.Test1() in C:\Test\Program.cs:line
39 at ConsoleApplication5.Program.Main(String[] args) in
C:\Test\Program.cs:line 19

倥絔 2025-01-09 00:11:31

异常的原始堆栈跟踪存储在 Exception 类的一个字段中。如果您想在不创建自己的异常类型的情况下删除它,您可以通过反射将其删除,如下所示:

[Serializable] 
public sealed class NoStackTraceException : OnExceptionAspect 
{
    public override void OnException(MethodExecutionArgs args)
    {
       RemoveStackTrace(args.Exception);
    }

    private void RemoveStackTrace(Exception exception)
    {
        FieldInfo stackTraceField = typeof(Exception).GetField("_stackTrace",
             BindingFlags.NonPublic | BindingFlags.Instance);
        if (stackTraceField != null)
        {
            // sets the value of _stackTrace to null
            stackTraceField.SetValue(exception, null);
        }
    }
}

您的异常将不再包含堆栈跟踪。

编辑 当然,你也可以在没有 PostSharp 的情况下完成同样的事情,只需在 catch 块中完成即可。

The original stack trace of the exception is stored in a field in the Exception class. If you want to remove it without creating your own exception type, you can remove it via reflection like this:

[Serializable] 
public sealed class NoStackTraceException : OnExceptionAspect 
{
    public override void OnException(MethodExecutionArgs args)
    {
       RemoveStackTrace(args.Exception);
    }

    private void RemoveStackTrace(Exception exception)
    {
        FieldInfo stackTraceField = typeof(Exception).GetField("_stackTrace",
             BindingFlags.NonPublic | BindingFlags.Instance);
        if (stackTraceField != null)
        {
            // sets the value of _stackTrace to null
            stackTraceField.SetValue(exception, null);
        }
    }
}

Your exception will no longer contain the stack trace.

Edit Of course you can accomplish the same thing without PostSharp too, just do it in the catch block.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文