Search

'Dependency Property'에 해당되는 글 1건

  1. 2008.09.25 왜 Dependency Property는 public static readonly로 선언하는가? (4)

WPF에서 가장 중요하고도 이해하기 힘든 부분이 이 Dependency Property인 것 같습니다. WPF로 프로젝트를 진행하면서 가장 이해안가는 부분이 이 Dependency Property의 선언이었습니다. MSDN과 기타 WPF책들을 보면 Dependency Property를 public static readonly로 선언하라고 "권장" 하고 있습니다. 어떤 책에는 "관습"이란 단어로 표현하기도 하더군요. 그 이유가 너무 궁금해 Dependency Property를 private 로 선언한 후 사용해 본 적도 있습니다. 그런데 잘 되더군요. ^^;;; 그렇다면 왜 Dependency Property를 public static readonly로 선언하라고 권장하는 것일까요?

어떻게static으로 선언해도 서로 다른 Object는 다른 값을 가질 수 있지?

일단 static으로 선언한다는 것이 가장 이해가 잘 안 갔습니다. Static 으로 선언된 멤버는 정적 메모리에 단 하나만 존재하게 됩니다. Button을 예로 들어 볼까요? Button등 Control에는 NameProperty라는 Dependency Property가 있습니다. 물론, static으로 선언 되어 있지요.

Button button1 = new Button { Name = "button1" };

Button button2 = new Button { Name = "button2" };

Button button3 = new Button { Name = "button3" };

Button button4 = new Button { Name = "button4" };

위와 같은 프로그램이 있다고 생각합시다. Name이란 Property는 NameProperty(Dependency Property)에 대응되는 Property입니다. 누군가 이렇게 질문했다고 합시다. "NameProperty는 static으로 선언 되어 있어. 따라서 위 코드를 실행시킨 후에는 button1, 2,3,4의 Name은 button4로 동일해야 하지 않을까?

여러분은 위 질문이 잘못된 것임을 알고 있습니다. 그런데 왜 그런걸까요? 분명히 NameProperty는 static으로 선언 되어 있는데 말입니다. 그 비밀은 DependencyObject의 SetValue, GetValue가 가지고 있을 것 같습니다. 보통 관습적으로 Dependency Property에 대응되는 Property는 다음과 같이 구현됩니다.

public string Name

{

set{ SetValue(NameProperty, value);}

get { return (string)GetValue(NameProperty);}

}

만약에 SetValue함수가 정적 공간에 value값을 저장한다면 위의 질문처럼 되야 할 것입니다. 그런데 button1,2,3,4의 Name 값이 서로 다르게 나타나는 것으로 보아 DependencyObject의 SetValue함수는 Dependency Property의 value를 정적 공간에 저장하지 않음을 알 수 있습니다. 그렇다면 어디에 저장하는 것일까요?

사실 DependencyObject는 Dependency PropertyValues라는 Dictionary를 가지고 있습니다.

private IDictionary<Dependency Property, object> Dependency PropertyValues;

DependencyObject는 Dependency Property를 키 값으로 해서 실제 value를 dictionary에 저장하는 것을 알 수 있습니다. 이로서 왜 static으로 저장해도 여러 Instance의 동일한 Dependency Property에 대응되는 Property의 value값이 다른지 알 수 있네요. 또한 여기서 다음과 같은 깨달음을 얻을 수도 있겠습니다.

Dependency Property는 실제 Instance의 Property Value를 얻고 저장하기 위한 Key로 사용된다.

왜 public static readonly로 선언하는가?

위에서 우리는 Dependency Property가 static으로 선언되어도 이에 대응되는 Property가 다른 값을 가질 수 있는지 알 수 있었습니다. 또한 Dependency Property는 자신 스스로의 Dependency Property객체에 value를 저장하지 않는다는 사실도 유추 할 수 있었습니다. 그렇다면 Dependency Property는 어떠한 역할을 하는 것일까요? 단지 value를 찾기 위한 Key로 활용되는 거라면 이 녀석이 필요하지 않을 지도 모릅니다. 또한 DependencyObject의 Setvalue함수가 단지 DependencyPropertyValues[DependencyProperty] = value;와 같이 단순하게 구현되었다면 Dependency Property는 필요 없었겠죠. (사실 DependencyObject의 SetValue함수는 실로 복잡해서 도저히 덤빌 욕구가 안나게 만듭니다.)

여러분도 아시다시피 Dependency Property는 실로 엄청난 일을 해냅니다. 부모 tree로 부터의 값 상속 이라던지, 자동 변경 통지 기능, Template 등등.. 이런 일을 해내기 위해 Dependency Property Object가 존재합니다. Dependency Object는 Dependency Property의 값을 결정하기 위해 Dependency Property 객체를 참고 합니다. Dependency Property에 metadata와 이름, owner Type이 필요한 것은 이 때문입니다. DependencyObject의 SetValue함수는 단순히 value를 dictionary에 저장하는 것이 아니라 현재 자신의 환경?에 맞게(자신의 VisualTree의 위치, Style값 등등) 저장하는데 이 때 Dependency Property의 특성 정보가 적극 활용되는 것입니다.

Dependency Object는 Dependency Property의 metaData와 다중 Provider를 이용해 Dependency Property의 최종 값을 결정한다.

Dependency Property는 자신 스스로가 value값을 가지고 있지 않으며 단지 value값을 결정하는데 필요한 정보를 가진다.

그렇다면 왜 Dependency Property가 public static readonly로 선언하라고 권장하는 것일까요? 제가 생각하는 이유는 다음과 같습니다. 먼저 Dependency Property의 정보를 다른 객체에 노출해야 할 필요가 있기 때문입니다. Binding을 예로 들겠습니다.

Binding bind = new Binding();

bind.Source = this;

bind.Path = new PropertyPath(Window.NameProperty);

canvas1.SetBinding(NameProperty, bind);

( 코드는 아무 짝에도 쓸모없는 코드입니다. 절대 쓰지 마세요^^;;;)

Window의 NameProperty를 canvas1의 NameProperty에 binding하고 있는 정말로 쓸데없는 코드군요. 다만 살펴봐야 할 것은 binding을 사용할 때 bind의 Source가 될 Instance와 Path로 사용될 Dependency Property가 필요하다는 것입니다. 아마 Binding을 수행하기 위해 Window의 NameProperty라는 DependencyProperty정보가 필요하기 때문일 것입니다. Binding 뿐만이 아니라 Style, Template, Animation등도 Dependency Property의 정보를 필요로 합니다. 이로서 public 으로 DependencyProperty를 노출하는 이유는 조금 알겠군요. 그런데 왜 굳이 public static으로 선언할까요? 그냥 선언하고 Property나 함수로 노출하면 안될까요? 물론 이렇게 해도 상관없습니다. 만약 여러분이 DependencyProperty를 Interface로 노출시키고 싶다면 private 로 선언하고 Property나 함수로 접근을 허용해도 상관 없습니다. 다만 이럴 경우가 거의 없다는 것이죠. 그리고 여러 Instance를 생성시켜도 Dependency Property객체가 변할 필요성이 없기 때문에 public static readonly로 선언하게 되는 것입니다.

 

Dependency Property, Visual Tree, Routed Event는 WPF를 이루는 가장 중요한 3대 요소 입니다. 특히 Dependency Property는 이해하기 어려우면서도 정말 신기한 놈입니다. WPF를 만든 사람에게 어떻게 이런 생각을 했냐고 물어보고 싶네요 ^^;;

신고


 

티스토리 툴바