【wpf】[踩坑日记] “组件“XXX”不具有由 URI“XXX“识别的资源”

报错背景

这是一个和反射相关的奇怪问题:

具体报错如下:

 报错的地方是:

这里是我想通过,prism提供的方式,弹出一个子窗口。这里prism应该也是用到的反射技术。

本来这段代码是正常工作的。

但是,在此段代码执行之前,我加了一段代码,也对这个界面的DLL进行了反射:

结果, prism就表示,找不到那个界面了。注释掉,这段反射,prism ShowDialog 又可以了。

感觉就是我对这个DLL反射之后,影响了prism的反射。

于是,我查找资料,发现有个博主和我遇到了类似的情况:

Wpf: “组件“XXX”不具有由 URI“XXX“识别的资源”的一个可能原因-IT Blog (itcn.blog)https://itcn.blog/p/18401329759.html

解决方案

解决方法,仅仅就是,将 LoadFile 改为 LoadFrom 即可!

LoadFile和LoadFrom

于是我去查了下 LoadFile 和 LoadFrom 有啥差异。他们之间主要有两个差异:

1 LoadFile()不会解析任何依赖

Assembly.LoadFile只载入相应的dll文件,比如Assembly.LoadFile("abc.dll"),则载入abc.dll,假如abc.dll中引用了def.dll的话,def.dll并不会被载入。

2 LoadFrom会解析依赖

Assembly.LoadFrom则不一样,它会载入dll文件及其引用的其他dll,比如上面的例子,def.dll也会被载入。

3 LoadFile()可以多次加载同一程序集

4 LoadFrom()不会重新进行加载已经加载过目标程序集

问题分析

应该是我使用了LoadFile() 相当于对dll,进行第二次的加载。第一次应该是prism进行加载的。我加载了之后,应该改变了什么,导致prism找不到之前加载的DLL了。

首先,要确定一下,prism是不是确实已经先加载过了:

我们可以在我们反射之前,通过调用函数,查看已经加载了哪些Assembly:

var aaa = AppDomain.CurrentDomain.GetAssemblies();

然后,打断点,发现确实已经有了:

如果再调用LoadFile,再次查看:

好家伙,aaa变量里 多了一个一模一样的Assembly。

反之,如果用LoadFrom确实就没有重复的加载。可能多了一个把prism搞懵逼了吧。

小结

那是不是LoadFrom就一定比LoadFile好用呢?(注意以下结论,我并未验证)

答:不一定。

        首先LoadFrom效率上会更低。

        其次同一台机器可能存在相同标识的多个程序集,而LoadFrom不会重复加载相同标识的程序集,这会导致,LoadFrom加载的不是你指定的程序集。解决方式一个取更特殊的名字,二是给程序集设置版本号,确保它的唯一性。

posted @ 2022-12-08 10:33  宋桓公  阅读(613)  评论(0编辑  收藏  举报