WPF控制丢弃由URI丢失的资源'例外

时间:2011-02-14 14:08:41

标签: c# wpf

在加载插件并尝试创建“XYZ”控件时,应用程序抛出以下异常:

  

“组件'XYZ'没有   URI标识的资源   '/ThePluginAssembly;component/XYZ.xaml'”   on中的InitializeComponent()方法   UserControls构造函数。

关键点是:

  1. 用户控件位于插件程序集

  2. 我正在尝试从插件程序集

  3. 中创建usercontrol
  4. 插件与主应用程序位于同一目录中

  5. 用户控件只有在通过XAML创建时才会出现问题。我在同一个程序集中有几个其他用户控件,但我使用代码实例化这些用户控件。当我尝试在XAML中创建UserControl时,我只收到错误消息。

  6. 在做一些谷歌时,我意识到当我的插件的两个实例加载到应用程序中时会发生这种情况。当我从其中一个文件夹中删除我的插件时(我允许从两个位置加载此插件),此异常停止重复发生。

    我的问题:

    1)WPF尝试解析URI以加载我的控件的原因是什么?

    2)我是否有办法在应用程序中加载我的插件的两个实例,并以某种方式摆脱这个异常?或者某种方式为每个实例创建一个唯一的URI(如果此异常是由冲突的URI引起的)。

    任何评论或参考都会有所帮助。

    感谢您的关注。

    编辑: 与Phil发布的问题相同:How to force WPF to use resource URIs that use assembly strong name? Argh!

6 个答案:

答案 0 :(得分:9)

执行此操作的唯一方法是在URI中包含版本信息,以便XAML加载程序可以区分正确的类型。这篇MSDN文章解释了Pack URI格式,Version部分有这样的描述:

  

; Version [可选]:包含资源文件的引用程序集的版本。当加载两个或多个具有相同短名称的引用程序集时,将使用此方法。

所以你想要使用以下之一:

/ThePluginAssembly;v1.0.0.0;component/XYZ.xaml
/ThePluginAssembly;v1.1.0.0;component/XYZ.xaml

答案 1 :(得分:2)

尝试使用Assembly.LoadFrom()代替Assembly.Load()Assembly.LoadFile()

我遇到了同样的问题:我曾经用Assembly.LoadFile()加载程序集。搜索了几天后,我发现Assembly.LoadFile()Assembly.Load()已被弃用。两种方法都会在运行时中产生问题。所以我使用Assembly.LoadFrom()并且它有效。

答案 2 :(得分:1)

以下说明与插件的程序集和插件引用的任何非系统程序集相关(复制可以在任何引用级别)。

由于插件的程序集位于应用程序的可执行目录中,因此 如果您将程序集添加到GAC,请将其从那里删除。

从解决方案中检查对程序集的所有引用,并将“Version Specific”设置为false。

如果插件程序集来自另一个解决方案,并且您使用不同版本的程序集进行调试/发布或x86 / x64,则编辑引用程序集的.csproj文件并设置引用路径,如this example

考虑取消对插件程序集的引用并使用反射来加载它们 - 这将删除插件上解决方案的依赖关系。
为此,您需要将任何在插件中查找特定元素的代码移动到插件程序集本身,并从原始解决方案中仅移动插件所公开的访问类型,这些类型支持插件外部定义的接口(通过原始解决方案中的程序集或程序集中的程序集)由原始解决方案和插件引用) - 通过反射访问程序集时,请确保从应用程序的可执行目录中加载程序集。

确保资源的Pack URI符合以下格式: “包://应用:,,, / ReferencedAssembly;组件/子文件夹/ ResourceFile.xaml”

答案 3 :(得分:0)

到目前为止,我已达到的最佳解决方案是在项目属性中修改插件dll的名称,并使其特定于版本。

所以,如果最初它是“prod.myplugin”,那么现在我已经把它变成了“prod.myplugin_300d3”。在重建项目时修改项目属性后,编译器重新生成.g.cs文件,现在它在URI中有一个版本(它显示为/prod.myplugin_300d3;component/XYZ.xaml),因此使我的URI成为独一无二的不同版本。

我仍在寻找更好的自动化解决方案,我可以修改MSBuild:编译配置。

答案 4 :(得分:0)

将bin文件夹中的所有文件复制到解决方案中所有项目的单独文件夹中,并从每个项目的bin文件夹中删除调试和发布文件夹。这解决了我的设计师问题。

请记住,下次编译时,所有文件将再次返回。因此,您必须在后期构建中安装一些脚本才能复制到另一个文件夹并删除bin文件夹下的文件。

答案 5 :(得分:0)

我遇到了同样的问题,我的UserControls都引用了与主应用程序xaml相同的Assembly。 从UserControls删除资源链接可解决此问题。