Элемент управления WPF, исключающий исключение "ресурса, идентифицированного отсутствием URI"
При загрузке плагина и попытке создания элемента управления "XYZ" приложение выдает следующее исключение:
"Компонент" XYZ "не имеет ресурс, идентифицированный URI" /ThePluginAssembly;component/XYZ.xaml" по методу InitializeComponent() в конструктор UserControls.
Ключевыми моментами являются:
-
Пользовательский элемент управления находится в сборке плагинов
-
Я пытаюсь создать usercontrol изнутри сборки плагинов
-
Плагины расположены в том же каталоге, что и основное приложение
-
Пользовательские элементы управления имеют проблемы только при их создании через XAML. У меня есть несколько других пользовательских элементов управления в одной и той же сборке, но я создаю их с помощью кода. Я получаю сообщение об ошибке при попытке создать UserControl в XAML.
При выполнении некоторых google я понял, что это происходит, когда в приложение загружаются два экземпляра моего плагина. Когда я удалял свой плагин из одной из папок (я разрешаю загрузку этого плагина из двух мест), это исключение перестает повторяться.
Мои вопросы:
1) В чем причина того, что WPF пытается разрешить URI для загрузки моего элемента управления?
2) Не существует способа, которым я мог бы иметь два экземпляра моего плагина, загруженного в приложение, и каким-то образом избавиться от этого исключения? или каким-либо образом создать уникальный URI для каждого экземпляра (если это исключение вызвано конфликтующим URI).
Любой комментарий или ссылка будут полезны.
Спасибо за ваш интерес.
Изменить:
Та же проблема, что и Фил: Как заставить WPF использовать URI ресурсов, которые используют сильное имя сборки? Argh!
Ответы
Ответ 1
Единственный способ сделать это - включить информацию о версии в свой URI, чтобы загрузчик XAML мог различать правильный тип. Эта статья MSDN объясняет формат URI пакета, а часть версии имеет это описание:
; Version [optional]: версия ссылочной сборки, которая содержит файл ресурсов. Это используется, когда загружаются две или более ссылочные сборки с таким же коротким именем.
Итак, вы хотите использовать одно из следующих значений:
/ThePluginAssembly;v1.0.0.0;component/XYZ.xaml
/ThePluginAssembly;v1.1.0.0;component/XYZ.xaml
Ответ 2
попробуйте использовать Assembly.LoadFrom()
вместо Assembly.Load()
или Assembly.LoadFile()
.
У меня была та же проблема: я загружал сборки с помощью Assembly.LoadFile()
. После поиска дней я обнаружил, что Assembly.LoadFile()
и Assembly.Load()
устарели. Оба метода создают проблемы во время выполнения. Поэтому я использовал Assembly.LoadFrom()
, и он сработал.
Ответ 3
Следующие указания относятся как к сборке плагинов, так и к любой несистемной сборке, на которую ссылается плагин (дублирование может быть на любом уровне ссылок).
Поскольку сборка плагинов находится в исполняемом каталоге приложения,
если вы добавили свою сборку в GAC, удалите ее оттуда.
Проверьте все ссылки на сборку из вашего решения и установите для параметра "Спецификация версии" значение false.
Если сборка подключается из другого решения, и вы используете разные версии сборки для debug/release или для x86/x64, тогда отредактируйте файлы .csproj, ссылающиеся на сборку, и установите ссылочный путь, как в этот пример.
Рассмотрите возможность отмены ссылки на сборки плагинов и использование отражения для их загрузки - это позволит удалить зависимости решения при подключаемых модулях.
Для этого вам нужно будет переместить любой код, который ищет определенные элементы в плагинах, самим сборщикам плагинов и из исходного решения только типы доступа, открытые плагином, которые поддерживают интерфейсы, определенные вне плагина (посредством сборок в оригинальном решении или в сборке на которые ссылаются как оригинальное решение, так и плагин).
- При доступе к сборке через отражение убедитесь, что вы загрузите сборку из исполняемого каталога приложения.
Убедитесь, что Pack URI ресурсам:
"Пакет://Применение:,,/ReferencedAssembly; компонент/подпапки/ResourceFile.xaml"
Ответ 4
До сих пор лучшее решение, к которому я добрался, изменяет имя моей плагины dll в свойствах проекта и делает его специфичным для версии.
Итак, если изначально это был "prod.myplugin", теперь я сделал это "prod.myplugin_300d3". После изменения свойств проекта, когда я перестраиваю проект, компилятор регенерирует файлы .g.cs, и теперь он имеет версию в URI (она отображается как /prod.myplugin_300d3;component/XYZ.xaml) и, таким образом, делает мой идентификатор URI в разных версиях.
Я все еще ищу лучшее, автоматическое решение, в котором я мог бы изменить конфигурацию MSBuild: Compile.
Ответ 5
Скопируйте все файлы из папки bin в отдельную папку из всех проектов, находящихся в вашем решении, и удалите папку отладки и выпуска из папки bin каждого проекта. Это решило проблему дизайнера для меня.
Помните, что при компиляции в следующий раз все файлы снова вернутся. Таким образом, вы должны иметь некоторую script в пост-сборке, чтобы скопировать в другую папку и удалить файлы из папки bin.