2012-02-02 4 views
6

throw 된 예외를 잡아 내고 StackTrace 속성을 string.Empty으로 설정하는 함수 (또는 클래스)에 대한 특성을 쓰고 싶습니다. 어떻게해야합니까?예외를 포착하고 stacktrace를 제거하는 속성을 작성하는 방법은 무엇입니까?

편집 :

나는 일반 C#에서이 작업을 수행 할 수없는 경우, 어떻게 PostSharp와 C#에서이 작업을 수행 할 수 있습니까?

+1

호기심 : 왜 이것을하고 싶습니까? –

+1

아래 답변을 참조하십시오. 예외가 발생했을 때 디버깅을 돕기 위해 예외가 존재합니다. 스택 추적을 제거하면 오류의 원인을 효과적으로 숨길 수 있습니다. 디버깅하지 않는 경우에는 찾을 수 없습니다.어떤 이유로 프라이버시가 걱정된다면, 스택 추적을 난독 화하거나 다른 방법으로 암호화 할 수 있습니다 (답안에 설명 된 것과 동일한 방법을 사용). 나중에 로그 파일에서 해독 할 수 있습니다. –

+0

이것은 내가 필요로하는 것이고, 이유는 웹 서비스에 Exception 객체를 전달해야하기 때문입니다. 그러나 어떤 이유로 서비스를 받아 들일 수 없습니다. 그래서 Message와 StackTrace를 전달한 다음 예외 서버 측을 다시 생성 할 수 있습니다. – ganders

답변

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의 예는 이미 같은 스택 추적으로 던져진 예외를 단순히 재현합니다 (aspect에 어떻게 접근했는지는 동일합니다). 새 예외를 던지면 스택 추적이 "변경"되지만 지우지는 않습니다. 지우려면 스택 추적 특성을 무시하는 클래스를 직접 작성해야합니다. 이전 예외를 새 예외로 전달하면 이전 예외가 내부 예외가됩니다 (원하는 경우)

PostSharp를 사용하거나 사용하지 않고이 작업을 수행 할 수 있습니다. 키는 사용자 정의 예외 클래스입니다. Program.cs \ \의 T의 EST : 라인 69

다음 코드 감안

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; 
    } 
} 

출력 C에

ConsoleApplication5.MyAspect.OnException에서

(MethodExecutionArgs 인수) 인 ConsoleApplication5.Program.Test3() in C : \ Test \ Program.cs : 줄 59
at ConsoleApplication5.Program.Test2() in C : \ Test \ Program.cs : 줄 47

ConsoleApplication5.MyAspect.OnException에서 15,

(MethodExecutionArgs 인수)에서 C : Program.cs \ \의 T의 EST : C에서 ConsoleApplication5.Program.Test3()에서 라인 (69) : \ 테스트 \ Program.cs : 라인 (59)을
ConsoleApplication5.Program.Test2()에서의 C : \ 테스트 \ Program.cs : \ 테스트 \ Program.cs : ConsoleApplication5.Program.Test1() C에서의 라인 (52)
라인 (34)

ConsoleApplication5.Program에서 .Test1() in C : \ Test \ Program.cs : 39 ConsoleApplication5.Program.Main (String [] args) C : \ Test \ Program.cs : 줄 19

+1

맞춤 클래스가 없으면이를 수행 할 수있는 방법이 있습니까? 예를 들어, 던져진'System.Exception'의 스택 추적을 제거하고 싶다면? – cm007

+0

당신은 반사를 알기 쉽게 사용할 수 있지만 실제로 이것은 프로덕션에서하고 싶은 것이 아닙니다. 나는 그것이 학문적이거나 시험을 위해서만 바라고 있습니다. @hmemcpy 대답을 참조하십시오. –

+0

Test1() 메서드에서 "throw e;"하는 이유는 무엇입니까? "던지기"대신에? – ganders

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 블록에서 수행하십시오.

관련 문제