프로그래밍을 하다보면 결과나 상태를 확인해야할 때가 많습니다.
디버깅 시에 호출 스택(Call stack)을 살펴보는 방법이나 지역 변수, 컨텍스트 등을 확인하는 것 또한 많은 도움이 됩니다.
하지만, 스레드가 작업을 하는 경우는 이야기가 달라집니다. 호출 스택에선 볼 수가 없더군요 - _-;;
그리고 작업 도중에 디버그를 할 경우에 외관을 볼 수 없는 윈도우 어플리케이션 같은... (메세지 처리가 중단됩니다) 까다로운 녀석들을 상대로도, 게임 프로그래밍을 할 때도 마찬가지입니다.
이럴 땐, System.Diagnostics 네임스페이스에 있는 Debug 클래스의 Print 메서드를 사용하여 출력 창에 찍는 방법이 있습니다.
출력 창에 로그를 남기는 것은 .NET의 강점이라고 볼 수 있을만큼 유용하게 사용됩니다.
이 메서드를 어떻게 사용하느냐에 따라 유용하고, 속도 저하의 원인이 되는지가 갈리게 됩니다.
호출되고 있는 메서드를 보려면 MethodBase 클래스의 정적 메서드인 GetCurrentMethod() 를 사용해도 되지만, StackTrace 클래스 및 StackFrame 클래스를 사용해도 가능합니다. 하지만, 이번 글에선 현재 호출되고 있는 메서드의 이름만 구할 것이기 때문에 간단하게 MethodBase 클래스의 GetCurrentMethod() 를 살펴보도록 하겠습니다.
public static MethodBase GetCurrentMethod();
MethodBase를 반환하게 되어있네요. (MethodBase 클래스 참조 문서, MSDN)
(MethodBase.GetCurrentMethod().GetCurrentMethod().GetCurrentMethod() .....ㅋㅋㅋㅋㅋㅋㅋㅋㅋ)
그리고 GetCurrentMethod() 에 대한 문서도 링크를 해야겠죠?
(GetCurrentMethod 메서드 참조 문서, MSDN)
MSDN의 문서에도 친히 '현재 실행하고 있는 메서드를 나타내는 MethodBase 개체를 반환합니다.' 라고 설명하고 있습니다. 그럼 저 개체를 가지고 어떻게 이름을 가져오느냐? 방법은 매우 간단합니다. MethodBase 클래스의 Name 속성을 이용하는 것. 그게 끝입니다.
그럼 실 사용 예를 한번 보도록 하겠습니다.
using System;
using System.Reflection;
namespace CSharpRef {
class Program {
public static void Main(string[] args) {
MethodBase ctxMethod = MethodBase.GetCurrentMethod();
Console.WriteLine("Current Method Information:");
Console.WriteLine(" Name : {0}", ctxMethod.Name);
Console.WriteLine(" FullName : {0}.{1}", ctxMethod.ReflectedType.FullName, ctxMethod.Name);
Console.WriteLine(" Static Method: {0}", ctxMethod.IsStatic);
Console.WriteLine(" Public Method: {0}", ctxMethod.IsPublic);
Console.ReadKey(true);
}
}
}
예제 코드의 실행 결과입니다.
메서드의 이름이나 한정자가 맞게 나온 것을 확인하실 수 있습니다.
IsPrivate, IsFinal, IsAbstract 등등 다양한 속성들이 지원되기도 합니다.
정말로 메서드의 대한 전반적인 정보를 가지고 있기 때문에 이걸 응용하여 로깅을 더 확실하게 할 수 있게 됩니다.
예를 들면, 로깅을 할 때 메서드의 위치까지 출력하는 것입니다.
public static void PrintEx(String text, MethodBase loc) {
Debug.Print("{0}.{1} - {2}", loc.ReflectedType.FullName, loc.Name, text);
}
이런 식으로 코딩을 하고, 로깅이 이뤄지는 메서드에서는 선행 작업으로 GetCurrentMethod 메서드를 이용하여 현재 메서드의 정보를 받아온 후에 PrintEx 메서드의 매개 변수로 넘겨주기만 하면 되겠지요.
(StackTrace 및 StackFrame 클래스를 이용하면 선행 작업 없이도 호출 중인 메서드를 가져오는 것이 가능하지만, 이 글의 주제와는 맞지 않으므로 설명을 하지 않겠습니다)
로깅이 얼마나 효율적으로 변했는지 아래와 같은 코드 작성 후 직접 테스트해보았습니다.
public static void WhatIsWrongInThisMethod() {
MethodBase cmb = MethodBase.GetCurrentMethod();
try {
Int32 a = 100;
Int32 b = 0;
Int32 c = a / b;
} catch (Exception ex) {
PrintEx(ex.Message, cmb);
}
}
실행 결과입니다. 메서드의 위치가 표시되고 예외의 내용도 같이 표시가 되는 것을 볼 수가 있습니다.
이 처럼, 아주 간단한 방법으로 강력한 기능을 가진 로깅을 적용할 수 있습니다.
그리고, System.Reflection 네임스페이스에는 메서드, 모듈, 형식 등을 다루고 관리하는데에 필요한 클래스들이 모여있습니다.
추가로 MSIL(Microsoft Intermediate Language, 마이크로소프트 공통 언어)를 프로그래밍하는 것 또한 가능합니다.
관심있으신 분들은 자세히 살펴보는 것도 많은 공부가 될 거라 생각합니다.
긴 글 읽어주셔서 감사합니다!
'.NET > C#' 카테고리의 다른 글
바이트 배열로부터 폰트 만들기 (0) | 2014.10.22 |
---|---|
문자열을 값으로 변환하기 (0) | 2014.10.20 |
private, public, protected 그리고 internal?? 접근 한정자에 대해 알아보자. (3) | 2014.10.13 |
C#을 이용한 파일 다운로더 만들기! (5) | 2014.10.09 |
C#을 이용하여 간단한 1:1 비동기 채팅 프로그램을 만들어보자 - 클라이언트편 (26) | 2014.10.03 |