티스토리 뷰

Others

[C#] CallerMemberName Attribute

해구름 2023. 5. 19. 12:04
반응형

2012년 소개된 C# 5부터 사용 가능한 CallerMemberName Attribute를 사용하면 함수 호출자의 이름을 전달받을 수 있습니다.

예를들어 다음 소스코드를 실행하면, 컴파일러는 매개변수 callerName에 함수를 호출한 "Main"을 할당합니다.

[샘플코드]

static void Main(string[] args)
{
  DoWork();
}

//[CallerMemberName]를 사용하면, 컴파일러는 매개변수 callerName에 함수를 호출한 "Main"을 할당함
static void DoWork([CallerMemberName] string callerName = null) 
{
  Console.WriteLine("함수 호출자 이름 : " + callerName);
}

[실행결과]
실행결과

CallerMemberName은 컴파일 타임에 동작하기 때문에 성능저하의 문제도 없습니다. 이 코드가 특히 유용하게 사용되는 분야가 INotifyPropertyChanged 구현입니다.

[개선 전 코드]


public class UserViewModel : INotifyPropertyChanged
{
    private string _UserName;
    public string UserName 
    { 
        get { return _UserName; }
        set { SetProperty(ref _UserName, value, "UserName"); } //매번 PropertyName을 문자열로 전달해야함
    }

    public void SetProperty<T>(ref T storage, T value, string propertyName)
    {
        if (storage?.Equals(value) == true)
            return;
        storage = value;
        OnPropertyChanged(propertyName);
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
}

[개선 후 코드]

public class UserViewModel : INotifyPropertyChanged
{
    private string _UserName;
    public string UserName 
    { 
        get { return _UserName; } 
        set { SetProperty(ref _UserName, value); } //PropertyName을 생략 가능
    }

    public void SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) //[CallerMemberName] 추가
    {
        if (storage?.Equals(value) == true)
            return;
        storage = value;
        OnPropertyChanged(propertyName);
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
}

CallerMemberName과 더불어 CallerFilePath, CallerLineNumber도 유용하게 사용하실 수 있습니다. 이를 통해 로그 생성 코드를 훨신 간결하게 작성하실 수 있습니다.

public static void WriteError(string msg,
    [CallerMemberName] string callerMemberName = "",
    [CallerFilePath] string callerFilePath = "",
    [CallerLineNumber] int callerLineNumber = 0)
{
    string folderPath = Properties.Settings.Default.LogFolderPath;
    if (System.IO.Directory.Exists(folderPath))
        System.IO.Directory.CreateDirectory(folderPath);

    string fileName = DateTime.Now.ToString("yyyyMMddHHmmss") + "_Error.txt";
    string filePath = System.IO.Path.Combine(folderPath, fileName);
    string fileText = msg + "\r\n" 
        + "- 호출자명: " + callerMemberName + "\r\n" 
        + "- 파일경로: " + callerFilePath + "\r\n" 
        + "- 라인번호: " + callerLineNumber;
    System.IO.File.WriteAllText(filePath, fileText);
}

CallerMemberName는 .NET Framework 4.5, VisualStudio 2012부터 이용 가능합니다.

References

 

'Others' 카테고리의 다른 글

[C#] Object Clone  (0) 2023.05.24
[C#] StringComparison 열거형  (0) 2022.07.28
[Mail] SMTP 프로토콜  (0) 2022.07.07
OIDC(OpenID Connect)와 OAuth 2.0  (0) 2021.07.22
Token 기반 인증 vs Cookie 인증  (0) 2021.07.22
서버 하드웨어 구성  (0) 2021.07.16
실무에서 TDD의 장담점과 의사결정  (0) 2021.01.07
[AndroidStudio] Code Folding  (0) 2020.12.16
댓글