Каковы основные недостатки предоставления DependencyProperty через статическое свойство вместо статического поля? (F #) - PullRequest
10 голосов
/ 09 ноября 2010

Я обнаружил, что F # 2.0, по-видимому, больше не поддерживает публичные статические поля , что делает невозможным стандартный способ реализации DependencyProperty:

public static readonly FooProperty = DependencyProperty.Register(...);   // in C#

Мне не совсем нравится один предложенный обходной путь для F #, который включает объявление DependencyProperty как static mutable val и затем его инициализацию с static do ... (или как бы точно это идет).

Я пытался выставить DependencyProperty в качестве открытого статического свойства вместо открытого статического поля , которое, кажется, прекрасно работает в приложении WPF (I ' пробовали привязку данных и установщики стилей для свойства, оба с успехом):

type XY() =
   inherit Control()

   static let fooProperty =
      DependencyProperty.Register("Foo", typeof<string>, typeof<XY>) 

   static member public FooProperty with get () = fooProperty  // see update below:
   //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  // not required!

   member public this.Foo with get (): string = this.GetValue(fooProperty) :?> string
                          and set (x: string) = this.SetValue(fooProperty, x)

Есть ли какие-либо заметные недостатки в публикации свойства зависимостей как свойства, а не как поля? Потому что этот код выглядит для меня намного чище, чем предлагаемый обходной путь.


Обновление # 1: Я только что обнаружил, что в приведенном выше коде FooProperty (публичное свойство только для чтения) даже не требуется. Таким образом, можно пропустить строку, которую я выделил в приведенном выше примере кода, и все по-прежнему работает просто отлично. Мне теперь еще более любопытно, почему люди идут на такие длины, используя mutable val и т. Д., Когда это очевидно так просто? Я что-то упустил?


Обновление № 2: В комментарии ниже Роберт Джеппезен предоставил гиперссылку на страницу MSDN , в которой упоминается следующее:

Если вы не выполните этот шаблон именования [т.е. Foo & rarr; FooProperty] , дизайнеры могут не сообщать правильно ваше свойство, а некоторые аспекты приложения стиля системы свойств могут работать не так, как ожидалось.

Я протестировал Expression Blend 4 и обнаружил, что на него вообще не влияют, когда общедоступная статическая FooProperty полностью отсутствует.

1 Ответ

8 голосов
/ 10 ноября 2010

Да, имеет значение, используете ли вы общедоступное статическое поле или нет. Но, может быть, не существенная разница, в зависимости от ваших потребностей. Я объясню, где сам WPF ведет себя по-другому, а затем упомяну пару других ситуаций, в которых это также может быть проблемой.

Влияние на синтаксический анализ XAML, если вместо статического поля используется статическое свойство

Единственная часть самого WPF, которая фактически замечает, использовали ли вы статическое свойство или статическое поле, - это синтаксический анализатор XAML, и единственная ситуация, в которой это имеет значение, - это когда одно и то же имя свойства используется на нескольких уровнях. Это связано с тем, что наличие статического поля с соответствующим именем и оканчивающимся на «Свойство» используется для устранения неоднозначности между одноименными DependencyProperties на нескольких уровнях.

В одном месте вы увидите разницу, если вы определите свое свойство, используя общедоступное статическое свойство (или вообще ничего), а класс-предок имеет свойство DependencyProperty с тем же именем, используя общедоступную статическую field , свойство вашего предка будет использоваться вместо вашего.

Например, предположим, что создается элемент управления, имеющий свойство DependencyProperty с именем «Language». В FrameworkElement уже есть свойство «Язык» DependencyProperty, но если вы следуете стандарту и используете открытое статическое поле , все в порядке: ваше свойство «Язык» будет иметь приоритет. Но если вместо этого вы используете общедоступное статическое свойство , ваш XAML в конечном итоге установит свойство зависимостей FrameworkElement.Language, а не ваше.

Это может быть проблемой, если, например, выходит новая версия WPF с новым свойством зависимости, определенным для одного из ваших базовых классов. Например, если вы используете свойство «Depth», которое вы определили с помощью статического поля, а NET Framework 5.0 определяет свойство «Depth» в «Visual», ваше приложение не будет работать с новой версией NET Framework.

Другой сценарий, в котором это может иметь значение, - это изменение иерархии классов. В этом случае WPF пытается защитить вас от проблем с версиями, но его защита исчезает, если вы используете общедоступное статическое свойство вместо общедоступного статического поля . Самый простой сценарий - вы написали библиотеку, и люди используют вашу собственность. Если вы использовали общедоступное статическое поле , то их скомпилированное приложение на самом деле будет содержать имя вашего класса, поэтому ошибки не будет. Но если вы использовали открытое статическое свойство (или вообще ничего), их скомпилированное приложение будет ссылаться на него, используя имя производного класса. Таким образом, если иерархия наследования изменится или будет добавлено новое свойство, оно может затенить ваше исходное свойство даже в скомпилированном коде. Например, это может быть проблемой, если:

  • YourControl является производным от ThirdPartyGrid
  • YourControl был написан, когда ThirdPartyGrid не имел поля "Language", поэтому скомпилированный код ссылается на FrameworkElement.Language
  • Если поставщик ThirdPartyGrid добавляет свойство зависимости «Language», оно не повлияет на ваше приложение
  • Но , если FrameworkElement.Language был определен как общедоступное статическое свойство , добавление поставщика нарушит работу вашего приложения

Существуют еще более эзотерические ситуации, в которых это может иметь значение.

Влияние на инструменты дизайнера

Насколько я могу судить, ни Visual Studio, ни Expression Blend не ведут себя иначе, если вы определяете свойство с помощью открытого статического свойства вместо поля или даже если вы оставьте это полностью, кроме случаев, когда они сталкиваются с поведением синтаксического анализатора XAML, упомянутым ранее.

Но следует отметить, что существует множество сред разработки XAML, и поскольку модель использования статических полей так твердо установлена, они могут полагаться на это. Так что будьте бдительны.

Влияет на сам WPF, кроме разбора XAML

За исключением парсера XAML, ни одна часть WPF не заботится о том, что вы определили общедоступное статическое свойство, поле или вообще ничего. Вы можете использовать ваши DependencyProperties точно так же, как в каждом случае. Однако:

  1. Я не знаю гарантии, это всегда будет правдой, а
  2. Сторонний код может легко положиться на него
...