![]() |
|
Модераторы: gambit, Kefir, Partizan |
![]()
|
|
| Compositum |
|
|||
|
Senior developer ![]() ![]() Профиль Группа: Awaiting Authorisation Сообщений: 430 Регистрация: 6.1.2008 Где: Санкт-Петербург Репутация: 1 Всего: 1 |
Изучаю свойства зависимостей по книге Мак-Дональда и по МСДН. На данный момент прорисовывается некое понимание, или что-то вроде того, но сильно сбивает с толку такой момент - поле, представляющее объект свойства зависимостей должно быть public static readonly. С одной стороны пишут, что инициализацию поля нужно производить в статическом конструкторе класса - это понятно. С др. стороны - ежели поле static, то, оно относится к классу, а не к экземпляру.... А ежели оно еще и readonly - то изменять его нет возможности. Однако приведенный в книге код сбивает меня с толку (юзаем три свойства зависимостей):
Я понимаю, что если бы свойства зависимостей нельзя было бы вызывать на экземплярах класса и изменять их - от них бы было мало толку. Однако тем не менее данный код никак не вяжется у меня в голове со static readonly В упаковщике свойства для изменения оного мы юзаем SetValue(...), но... ведь оно readonly... Помогите разобраться плиз кто уже сам разобрался в сём вопросе. Это сообщение отредактировал(а) Compositum - 26.4.2009, 21:12 |
|||
|
||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 13 Всего: 59 |
Вся эта штука со свойствами зависимостей придумана для облегчения работы со свойствами, а именно их установкой, чтением, получением нотификации об изменении, валидации и т.д.
Начнем с того, что было до их изобретения. Если какому-либо классу требовалось, например, ссылаться на свойство другого класса в какой-либо момент времени, то единственный способ, чтобы это сделать, был хранить имя свойства в строковом поле. То есть идентификатором свойства было просто его имя!!! Недостатков у такого способа много. Во первых, чтобы установить или прочитать значение свойства, приходилось прибегать к инструментам Reflection (подробнее в инете, если не знаешь что это), а это штука весьма тормознутая в плане быстродействия. Во вторых, если необходимо было получать уведомления об изменении свойства, то класс, содержащий это свойство, должен был самостоятельно заботиться об этом. Стандартным способом была реализация интерфейса INotifyPropertyChanged, который сдержит в себе единственный член: событие PropertyChanged. При вызове события, в качестве параметра шло опять таки имя свойства. Если класс должен был уведомлять о нескольких своих свойствах, то возникала еще одна проблема: так как событие PropertyChanged вызывается для любого свойства (с передачей имени свойства), то класс-подписчик обязан был при получении уведомления проверять имя свойства для того, чтобы распознать, какое именно свойство изменилось. Другим вариантом, было использование схемы именования событий об ихменении свойств (событие должно было иметь имя ИмяСвойстваChanged). Этот вариант был более предпочтителен и применялся максимально везде, где только можно и имело смысл (для примера возьми любой Control, он преизбытучествует такими событиями). А к его недостаткам можно отнести то, что количество событий равно количеству свойств, которые хотят оповещать о своем изменении. И опять таки нужен был Reflection для того, чтобы получить ссылку на событие по имени. В третьих, о чем нам говорит имя свойства? Да ни о чем!!! Какой тип оно имеет? К какому классу оно относится (если мы имеем только имя свойства, без ссылки на экземпляр класса)? Короче, единоглассно было решено исправить это раз и навсегда! (ну может не навсегда, вдруг еще что-то придумают К чему я расписываю недостатки прошлого? Да к тому, чтобы было понятно, что свойство зависимостей решает все эти проблемы!!! Начну с примера, по которому буду прояснять:
Все, что мы делаем в третьей строке, так это объявляем КЛЮЧ (ИДЕНТИФИКАТОР) СВОЙСТВА!!! Все, конец всем нашим проблемам! Теперь вместо имени свойства (ни о чем не говорящего), у нас есть нормальный идентификатор, котрый несет в себе всю информацию о свойстве (метаданные). Сам NameProperty НЕ является свойством Name класса! Его допустимо рассматривать как идентификатор свойства (хотя на самом деле это больше, чем просто идентификатор). Само свойство, мы объявляем ниже, в строчках 5-9. Но где же мы его храним? У нас ведь нет поля? Верно, у нас нету. Само значение хранится внутри Framework'а, в специальном хранилище свойств. Хранилище можно себе представить (но только представить, а не принимать как факт) как Dictionary, ключем которого является поле NameProperty. this.GetValue(NameProperty) вытащит значение из хранилища, а this.SetValue(NameProperty, value) положит его туда. GetValue и SetValue реализованы в DependencyObject, от которого мы обязаны наследоваться, если хотим получить всю функциональность подсистемы DependencyProperty. Вот теперь понятно, почему NameProperty нужно и имеет смысл делать static readonly. Ведь сам идентификатор остается навсегда один и тот же, он не измеяется никогда и НЕ В КОЕМ СЛУЧАЕ НЕ ДОЛЖЕН. static - потому что он ОДИН для всех экземпляров данного класса, а readonly чтобы гарантировать, что он НЕ ИЗМЕНИТСЯ случайно где-нить в нашей программе. Таким образом мы получили механизм, который централизованно и в полне однозначно может представить ссылку на свойство, а также предоставить способы получения нотификации о его изменении и дополнительную (расширенную) информацию о нем самом. Использование DependencyProperty избавляет нас от использования тормознутого Reflection используемого ранее для доступа к реальному объекту, его свойствам и информации о них. Вот так-то! Фух, надеюсь это проясняет все, касательно этой подсистемы, а также будет полезным не только для тебя, но и для других наткнувшихся на эту тему -------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
| Compositum |
|
||||
|
Senior developer ![]() ![]() Профиль Группа: Awaiting Authorisation Сообщений: 430 Регистрация: 6.1.2008 Где: Санкт-Петербург Репутация: 1 Всего: 1 |
Не понял насчет сложности сослаться на свойство... Вот же все просто:
или я чего не верно понял? |
||||
|
|||||
| -Mikle- |
|
||||||||||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 13 Всего: 59 |
Я имел ввиду сослаться на свойство любого класса. Ну вот, например:
Задача класса, последовательно устанавливать значения свойства с именем в TargetProperty экземпляря объекта TargetObject. При том, что класс должен принимать любое свойство любого объекта, единственным способом сослаться будет использовать его имя. А для установки - использовать средства отражения. Более того, если бы задача была другая и требовала бы обратной связи со свойством (т.е. получения события о его изменении), то не было бы никакой гарантии того, что переданный в TargetObject объект имел бы какое-либо подобное событие. И даже если это объект наследник INotifyPropertyChanged, то все равно нет гарантии, что событие генерируется для свойства переданного в TargetProperty, так как генерация события лежит на программисте этого класса. А если объект в TargetObject не наследник INotifyPropertyChanged, то для поиска нужного события применялся бы опять таки тормознутый Reflection. Теперь перепишем пример на DependencyProperty:
Как видишь, использование DependencyObject и DependencyProperty реализует новый и гарантированный способ работы с любыми свойствами любого объекта. При этом, средства Reflection не привлекаются. Также мы имеем гарантию того, что если от свойства потребуется обратная связь (событие его изменения), то мы можем гарантированно ее получить, так как любое DependencyProperty реализует эту поддержку. Кстати, когда я говорил что
то я был не прав. Хранилище, это таки и есть Dictionary. Посмотрел рефлектором код DependencyObject и увидел это:
А установка свойства DependencyProperty сводится к
не считая дополнительного кода разных проверок и вызова нотификации. Так что работает это все довольно быстро -------------------- Если тебе плюют в спину, значит ты впереди... |
||||||||||
|
|||||||||||
| Compositum |
|
|||
|
Senior developer ![]() ![]() Профиль Группа: Awaiting Authorisation Сообщений: 430 Регистрация: 6.1.2008 Где: Санкт-Петербург Репутация: 1 Всего: 1 |
||||
|
||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 13 Всего: 59 |
Я не делал примеры готовыми к компиляции и работе. Сейчас я отредактировал немного код, так что скопируй код еще раз заново.
PS: Не получилось скомпилить у тебя, потому что первый пример надо компилить как WinForms приложение, а второй как WPF. -------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
| Compositum |
|
|||
|
Senior developer ![]() ![]() Профиль Группа: Awaiting Authorisation Сообщений: 430 Регистрация: 6.1.2008 Где: Санкт-Петербург Репутация: 1 Всего: 1 |
Спасибо за отклик. =)
Тем не менее с твоими ответами у меня все больше вопросов (на тех же твоих примерах): 1. Если рассматривать первый пример - ты обращаешься в коде к неинициализируемому строковому массиву, размер которого не известен. Не понял, что ты хотел сделать заюзав "%" (это вроде как получение остатка от деления, насколько я помню) - не понял той строки кода. 2. Во втором примере не вижу ни малейшего намёка как на использование FrameworkPropertyMetadata (которое вроде как не обязательно, но все же хотелось бы в ней разобраться), так и на регистрацию DependencyProperty, не говоря уже об всяких там проверках и т.п. В общем - все по прежнему достаточно туманно. |
|||
|
||||
| -Mikle- |
|
||||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 13 Всего: 59 |
Вобщем я приводил примеры с целью показать разницу в решении одной задачи с использованием и без использования DependencyProperty. Я не делал примеры готовыми для применения где-либо вообще, поэтому в них отсутствуют различного рода проверки на что-либо. Но тем не менее, чтобы тот пост не выглядел голословным, отвечу на твои вопросы.
1. Предполагалось, что массив будет инициализироваться снаружи, что вполне логично. Единственное что я не написал, так это проверку на null и на длину равной нулю. Но пример нёс иную цель, поэтому это не было написанно дабы не загромождать его. Эта строка
является альтернативой вот этим строкам:
поразмышляй, я уверен что ты в этом убедишься. 2. Второй пример не предназначен для демонстрации самих DependencyProperty (про их регистрацию я написал в первом посте). Он предназначен для демонстрации использования DependencyProperty. Оба примера вместе, демонстрируют разницу при решении одной и той же задачи. Перечитай свой вопрос из первого поста, тебе было не понятно почему public static readonly и мой первый ответ раскрыл это и еще я рассказал где хранится значение свойства физически. Далее, ты не понял на счет сложности ссылаться на свойство и я тебе привел два примера. Первый демонстрирует то, что я имел ввиду говоря про эту сложность (ссылка на свойство по имени), второй - это что ссылаться на DependencyProperty проще, красивее и быстрей по скорости выполнения. Также, в обоих ответах, я пытался продемонстрировать, что ссылаться на DependencyProperty более красивей, чем ссылка по имени свойства. Плюс ко всему, DependencyProperty предоставляет целый набор других фишек, таких как метадата и нотификация об изменении. Мой тебе совет: перечитай эту тему от начала и до конца внимательно. -------------------- Если тебе плюют в спину, значит ты впереди... |
||||
|
|||||
| musson |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 28.9.2008 Репутация: нет Всего: нет |
-Mikle-
Спасибо, все понятно изложено!!! |
|||
|
||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 13 Всего: 59 |
musson, рад помочь еще
-------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | WPF и Silverlight | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |