WPF控制抛出’由URI丢失标识的’资源’exception

在加载插件并尝试创建“XYZ”控件时,应用程序将引发以下exception:

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

关键点是:

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

  2. 我试图从插件程序集内部创建usercontrol

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

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

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

我的问题:

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

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

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

谢谢你的关注。

编辑:与Phil发布的问题相同: 如何强制WPF使用使用程序集强名称的资源URI? 哎呀!

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

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

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

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

尝试使用Assembly.LoadFrom()而不是Assembly.Load()Assembly.LoadFile()

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

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

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

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

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

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

确保资源的Pack URI的格式为:“pack:// application:,,, / ReferencedAssembly; component / Subfolder / ResourceFile.xaml”

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

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

我仍然在寻找一个更好的自动化解决方案,我可以在其中修改MSBuild:Compile配置。

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

请记住,当您下次编译时,所有文件将再次返回。 所以你必须在post build中有一些脚本才能复制到另一个文件夹并删除bin文件夹下的文件。