Подтвердить что ты не робот

Объединенные словари и поиск ресурсов

У меня проблема с ресурсными словарями и сложенными словарями в целом, особенно когда речь идет о производительности ресурса. После некоторого тестирования производительности я обнаружил, что ResourceDictionary.get_MergedDictionaries - это вызов с наибольшим количеством ударов (проверяется в профилировщике ANTS). У нас есть около ~ 300 ресурсных словарей xamls, и многие из них используют объединенный словарь для "включения" других стилей. Ну, get_MergedDictionaries рассчитывают на одну часть нашего приложения, где мало что происходит, было около 10 миллионов обращений. Поэтому я предполагаю, что мы делаем что-то совершенно неправильное с ресурсными словарями в целом. Поэтому я попытался реорганизовать все, и я хочу попытаться избавиться от всех объединенных словарей.

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

Один основной проект и одна пользовательская библиотека управления.

пользовательская библиотека управления содержит 2 xamls.

<!-- Colors.xaml -->
<ResourceDictionary [stripped namespaces] >
    <SolidColorBrush x:Key="myColor" Color="Green"/>
</ResourceDictionary>

<!-- Templates.xaml -->
<ResourceDictionary [stripped namespaces]>
    <ControlTemplate x:Key="myTemplate" TargetType="Button">
        <Rectangle Fill="{StaticResource myColor}"/>
    </ControlTemplate>
</ResourceDictionary>

Теперь в основном проекте MainWindow.xaml выглядит так:

<Window x:Class="ResourceTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/ResourceTestLib;component/Themes/Colors.xaml"/>
                <ResourceDictionary Source="/ResourceTestLib;component/Themes/Template.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Button Template="{StaticResource myTemplate}"/>
    </Grid>
</Window>

Это желаемая цель. но, к сожалению, это происходит из-за того, что ресурс "myColor" не найден. Я, конечно, знаю, как это исправить, добавьте объединенный словарь в Templates.xaml и ссылку Colors.xaml, но я всегда думал, что я никогда не проверял, что ресурсы просматриваются в зависимости от логического дерева и ресурсов элемента. Мое понимание; Создается кнопка; попробуйте найти шаблон.. found; попробуйте найти цвет, не найти на собственных ресурсах, подойти и использовать ресурсы Windows.

Кажется, я ошибаюсь. Поэтому я надеюсь, что кто-то может пролить свет на это для меня. Мы активно используем WPF, и, несмотря на это, мы многого добились с ним, но из-за неправильного обучения в начале, наша производительность довольно плохая только из-за поиска ресурсов. Любая помощь будет принята с благодарностью

Спасибо заранее С наилучшими пожеланиями Нико

4b9b3361

Ответ 1

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

Как я уже говорил, у нас много XAML, около ~ 300 для всех разных вещей, таких как Shared Resources (Brushes, Colors), а также много XAML, содержащих разные DataTemplates, стили для элементов управления, а также для пользовательских элементов управления. Вначале этот подход с большим количеством XAML был для нас разумным, потому что мы делаем то же самое с нашими классами и сохраняем их небольшими и организованными. К сожалению, WPF это не нравится. Чем больше ресурсов у вас есть и чем больше вы объедините их через MergedDictionaries, тем хуже будет ваша производительность. Лучший совет, который я могу вам дать, использовать как можно меньше ResourceDictionary XAMLs.

Мы запустили пулю и объединили много из них в один гигантский XAML, фактически мы делаем это сейчас с предварительным компилятором, сохраняющим лучшее из обоих миров. Мы можем использовать столько XAML, сколько хотим, просто следуя нескольким ограничениям и объединим их при компиляции в гигантском XAML. Увеличение производительности, которое мы получаем, было замечательным. В моем вопросе я написал "11 миллионов хитов на getMergedDictionaries"... просто "предварительно скомпилировав" одну из наших сборок, мы снизились до 2 миллионов просмотров, а производительность во всем приложении во все времена намного лучше.

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

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

Спасибо за все комментарии и предложения.

С уважением Нико

Ответ 2

Я склонен идти по пути использования только одного ResourceDictionary в приложении, чтобы избежать каких-либо проблем с производительностью.

Чтобы XAML был управляемым, я использую модуль XAML для Visual Studio и обертываю каждую категорию ресурсов в регионе.

  • Щетки
  • Стили текста
  • и т.д...

Для этого сценария плагин является абсолютным спасателем жизни. http://visualstudiogallery.msdn.microsoft.com/3c534623-bb05-417f-afc0-c9e26bf0e177

Ответ 4

Был ли какой-либо свет на процедуру поиска ресурсов? Почему "myColor" не найден?

Кстати, я нашел способ заставить его работать, но странный и неустойчивый способ. Если Application.xaml имеет этот код, цвет должен быть найден:
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/ResourceTestLib;component/Themes/Colors.xaml"/>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/ResourceTestLib;component/Themes/Template.xaml"/> 
        </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary>
</ResourceDictionary.MergedDictionaries>

Если, с другой стороны, вы включаете этот код в другой XAML, который затем включаете в Application.xaml - он не работает, хотя структуры ресурсов идентичны (проверено с помощью Snoop).