2023년 10월 30일 월요일

내가 이해한 Dependency Property

구글링을 하면 WPF의 Dependency Property에 대한 자료가 많이 나온다. 
차근차근 읽어보면 대략적으로 이해가 가는데 이것을 설명을 하자면 조금 답답한 감이 있다보니 개념을 나름데로 정리해봤다.

Dependency Property 를 간단하게 코드로 표현하면 아래와 같다.

public partial class ColorPickerCtrl : UserControl
{
...
public Brush SelectedColor
{
    get { return (Brush)GetValue(SelectedColorProperty); }
    set { SetValue(SelectedColorProperty, value); }
}
public static DependencyProperty SelectedColorProperty =
         DependencyProperty.Register("SelectedColor", typeof(Brush), typeof(ColorPickerCtrl), new UIPropertyMetadata(null));
...  
}

여기서 ColorPickerCtrl은 DependencyObject를 상속받는 클래스이며 Dependency Property를 소유하려면(has-a)
반드시 DependencyObject 를 상속받아야 한다.
찾아보면 Dependency Property 를 사용하는 이유는 아래와 같다.

메모리 절약, 값 상속, 변경값 noti, 기타(데이터 바인딩, 스타일 적용, 리소스 적용, 에니메이션 등등)

여기서부터 본인이 공부하는 입장이 아니라 WPF의 설계자(앤더스 헤일즈버그?)라고 가정하고 어떻게 구현할지 생각해보자.

위 기능들을 구현하려면 일반적인 프로퍼티(CLR Property)로는 구현이 불가능하다. 
프로퍼티이면서 일종의 "동적으로 관리되는" 프로퍼티라는 개념이 필요하다. 
"동적으로 관리된다"는 것의 의미는 컴파일 타임에 프로퍼티가 결정되는 것이 아니라 런타임에 프로퍼티가 결정된다는 것을 의미한다.

프로퍼티를 관리하려면 해당 프로퍼티에 대한 정보, 좀 더 구체적으로 말하면 프로퍼티의 메타 데이터가 필요하다.
그리고 이 프로퍼티 메타 데이터를 저장할 저장공간도 필요하다. 프로퍼티 메타 데이터를 프로퍼티 메타 데이터 저장소에 저장하려면 프로그램 실행 초기이든 실행 중간이든 programmatic하게 등록(저장)하는 과정이 당연히 필요하다.

위 코드에서 DependencyProperty.Register static 메소드가 이 역할을 하는 것이다.
SelectedColor 라는 객체(클래스를 인스턴스화 한것)의 프로퍼티에 대한 메타정보, 즉 SelectedColorProperty는 따라서 당연히 static이 되어야한다. 왜냐면 프로퍼티 메타정보는 인스턴스화 한 객체의 정보가 아니라 클래스의 정보이기 때문이다.

그리고 SelectedColor 프로퍼티의 get/set 은 일반 프로퍼티처럼 고정된 특정 변수를 엑세스하는것이 아니라 역시 programmatic하게 구현되어야 한다. 왜냐하면 SelectedColor의 메타데이터 즉, SelectedColorProperty가 programmatic하게 구현되었기 때문이다.
따라서 GetValue/SetValue 가 사용되는 것이다.