Как написать атрибут, который перехватывает исключения и удаляет трассировку стека? - PullRequest
6 голосов
/ 02 февраля 2012

Я хочу написать атрибут для функции (или класса), которая будет отлавливать любое выброшенное исключение и устанавливать для его свойства StackTrace значение string.Empty.Как я могу это сделать?

РЕДАКТИРОВАТЬ:

Если я не могу сделать это в простом C #, как я могу сделать это в C # с PostSharp?

Ответы [ 2 ]

3 голосов
/ 03 февраля 2012

Исходная трассировка стека исключения сохраняется в поле в классе 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);
        }
    }
}

В вашем исключении больше не будет трассировки стека.

Edit Конечно, вы можете сделать то же самое и без PostSharp, просто сделайте это в блоке catch.

3 голосов
/ 02 февраля 2012
[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 в ConsoleApplication5.Program.Test3 () в C: \ Test \ Program.cs: строка 59
в ConsoleApplication5.Program.Test2 () в C: \ Test \ Program.cs: строка 47

в ConsoleApplication5.MyAspect.OnException (MethodExecutionArgs args) в C: \ T est \ Program.cs: строка 69 в ConsoleApplication5.Program.Test3 () в C: \ Test \ Program.cs: строка 59
в ConsoleApplication5.Program.Test2 () в C: \ Test \ Program.cs: строка 52
в ConsoleApplication5.Program.Test1 () в C: \ Test \ Program.cs: строка 34

в ConsoleApplication5.Program.Test1 () в C: \ Test \ Program.cs: строка 39 в ConsoleApplication5.Program.Main (String [] args) в C: \ Test \ Program.cs: строка 19

...