Анализируются ли MergedDictionaries каждый раз?

Рассмотрим WPF UserControl, который определяет следующие ресурсы:

<UserControl.Resources >
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source = "LeftHeaderDataTemplates.xaml"/>
            <ResourceDictionary Source = "RightHeaderDataTemplates.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

Будут ли объединенные ресурсы анализироваться для каждого экземпляра пользовательского элемента управления? Временная шкала приложения в профилировщике производительности, похоже, указывает на это, но я не уверен, правильно ли я читаю результаты.

РЕДАКТИРОВАТЬ

Как указано в ответе @Andy: да, ResourceDictionary анализируется каждый раз, и создается новый экземпляр. В комментариях ниже он упомянул, что есть «лучший способ» для ссылки на конвертеры, а именно позволить им реализовать MarkupExtension, как показано в предоставленной им ссылке.

Это подняло вопрос о том, сколько экземпляров преобразователя создается в зависимости от того, каким образом на них ссылаются/реализуют. Я подумал, что добавлю сюда свои выводы, потому что нашел их актуальными в контексте моего первоначального вопроса.

Рассмотрим UserControl, который отображается 4 раза:

<UserControl>
    <UserControl.Resources>
        <converters1:TestConverter3 x:Key = "TestConverter3"/>
    </UserControl.Resources>

    <StackPanel Background = "Black">
        <TextBlock Foreground = "White" Text = "{Binding Converter = {StaticResource TestConverter1}}"></TextBlock>
        <TextBlock Foreground = "White" Text = "{Binding Converter = {StaticResource TestConverter1}}"></TextBlock>
        <TextBlock Foreground = "White" Text = "{Binding Converter = {converters1:TestConverter2}}"></TextBlock>
        <TextBlock Foreground = "White" Text = "{Binding Converter = {converters1:TestConverter2}}"></TextBlock>
        <TextBlock Foreground = "White" Text = "{Binding Converter = {StaticResource TestConverter3}}"></TextBlock>
        <TextBlock Foreground = "White" Text = "{Binding Converter = {StaticResource TestConverter3}}"></TextBlock>
    </StackPanel>
</UserControl>

Кроме того, TestConverter1 определяется как глобальный/общий/статический ресурс в App.xaml, а TestConverter2 реализуется путем наследования MarkupExtension.

Всего существует 3 разных преобразователя, каждый из которых используется дважды 4 экземплярами UserControl.

Это создало следующий вывод консоли (с добавленными пустыми строками):

CREATING: TestConverter1 {HashCode: 51949120}
                                             
CREATING: TestConverter2 {HashCode: 27832883}
CREATING: TestConverter2 {HashCode:  8329199}
CREATING: TestConverter3 {HashCode: 48129282}
                                             
CREATING: TestConverter2 {HashCode: 12052844}
CREATING: TestConverter2 {HashCode: 24470370}
CREATING: TestConverter3 {HashCode: 24336447}
                                             
CREATING: TestConverter2 {HashCode: 22270914}
CREATING: TestConverter2 {HashCode: 23473221}
CREATING: TestConverter3 {HashCode: 11043085}
                                             
CREATING: TestConverter2 {HashCode: 50932452}
CREATING: TestConverter2 {HashCode: 32788649}
CREATING: TestConverter3 {HashCode: 49189852}

Convert     : TestConverter1 {HashCode: 51949120}
Convert     : TestConverter1 {HashCode: 51949120}
Convert     : TestConverter2 {HashCode: 27832883}
Convert     : TestConverter2 {HashCode:  8329199}
Convert     : TestConverter3 {HashCode: 48129282}
Convert     : TestConverter3 {HashCode: 48129282}
                                                 
Convert     : TestConverter1 {HashCode: 51949120}
Convert     : TestConverter1 {HashCode: 51949120}
Convert     : TestConverter2 {HashCode: 12052844}
Convert     : TestConverter2 {HashCode: 24470370}
Convert     : TestConverter3 {HashCode: 24336447}
Convert     : TestConverter3 {HashCode: 24336447}
                                                 
Convert     : TestConverter1 {HashCode: 51949120}
Convert     : TestConverter1 {HashCode: 51949120}
Convert     : TestConverter2 {HashCode: 22270914}
Convert     : TestConverter2 {HashCode: 23473221}
Convert     : TestConverter3 {HashCode: 11043085}
Convert     : TestConverter3 {HashCode: 11043085}
                                                 
Convert     : TestConverter1 {HashCode: 51949120}
Convert     : TestConverter1 {HashCode: 51949120}
Convert     : TestConverter2 {HashCode: 50932452}
Convert     : TestConverter2 {HashCode: 32788649}
Convert     : TestConverter3 {HashCode: 49189852}
Convert     : TestConverter3 {HashCode: 49189852}

Полученные результаты:

  • TestConverter1, используемый/определяемый как статический ресурс в App.xaml, создается 1 раз.
  • TestConverter2, используемый/определяемый как расширение разметки, создается 8 раз (один раз для каждого использования).
  • TestConverter3, используемый/определяемый как статический ресурс в UserControl, создается 4 раза (один раз для каждого элемента управления).

Конечно, преобразователи должны быть легкими, поэтому это часто не будет проблемой (относительно памяти или сборки мусора), но я, тем не менее, подумал, что стоит понаблюдать, особенно если вы выберете действительно очень гладкий синтаксис MarkupExtension.

Да, это будет. И даже больше. Если вы установите DynamicResource, это будет работать аналогично привязке. При изменении ресурса, замене словаря, изменении уровня ресурса - значение DynamicResource будет оцениваться заново.

EldHasp 03.01.2023 07:51

@EldHasp: спасибо! если бы вы написали как ответ, я бы принял это как единственный; о)

mike 03.01.2023 08:17

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

Andy 03.01.2023 12:21

@Энди: да, теперь я вижу, это также относится ко всем ресурсам, например если ресурс является Converter, новый экземпляр будет создан для каждого UserControl.

mike 03.01.2023 12:43

Истинный. Но есть лучший способ сделать преобразователи.

Andy 03.01.2023 14:14

@Энди: ты дразнишь ;о) не мог бы ты уточнить?

mike 03.01.2023 17:49

drwpf.com/blog/2009/03/17/…

Andy 03.01.2023 19:09

@Andy: я изучил подход MarkupExtension, и у меня не было времени, чтобы изолировать и протестировать проблему, но на первый взгляд отладчик показывает, что в отношении создания экземпляра/мусора новый экземпляр создается каждый раз, когда ссылаются на конвертер, то есть даже больше раз, чем в разметке моего поста (где для каждого определения создается новый экземпляр).

mike 05.01.2023 18:23

Статика означает синглтон.

Andy 05.01.2023 19:40

@Andy: Да, конечно, static=singleton, но метод ProvideValue является методом экземпляра, его необходимо вызывать для фактического экземпляра (предположительно созданного WPF с использованием отражения), который затем возвращает общий/статический/одиночный экземпляр - вместо только себя.

mike 05.01.2023 21:19
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
10
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Да - будет.
И даже больше. Если вы установите DynamicResource, это будет работать аналогично привязке. При изменении ресурса, замене словаря, изменении уровня ресурса - значение DynamicResource будет оцениваться заново.

Другие вопросы по теме