如何编写捕获异常并删除stacktrace的属性?

时间:2012-02-02 14:31:43

标签: exception c#-4.0 stack-trace postsharp

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

修改

如果我在普通的C#中无法做到这一点,我怎么能用C#with PostSharp做到这一点?

2 个答案:

答案 0 :(得分:3)

[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行at   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行at   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:line中的ConsoleApplication5.Program.Test1()   39在ConsoleApplication5.Program.Main(String [] args)中   C:\ Test \ Program.cs:第19行

答案 1 :(得分:3)

异常的原始堆栈跟踪存储在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区块内完成。