使用Activator.CreateInstance创建的实例无法解析引用的原因

本文关键字:引用 Activator CreateInstance 创建 实例 使用 | 更新日期: 2023-09-27 18:23:58

我有一个具有以下文件夹结构的应用程序:

Application'Modules'XXX

当然,XXX内部的任何程序集都会在XXX内部找到其他程序集。

问题发生在一些使用反射实例化的实例上:

TProvider providerInstance = (TProvider)Activator.CreateInstance(providerType));

TProvider有一个方法,它返回在另一个程序集中定义的类(也存储在XXX中)。当调用必须加载引用的providerInstance的方法时,我会得到一个FileNotFoundException,说明即使依赖项在同一XXX文件夹中,也找不到依赖程序集。

查看融合日志,程序集加载程序只检查应用程序文件夹,而不是XXX。。。

你知道为什么会发生这种情况以及如何解决吗?

谢谢。

使用Activator.CreateInstance创建的实例无法解析引用的原因

原因是您使用LoadFile方法加载程序集:

LoadFile不会将文件加载到LoadFrom上下文中,也不会使用加载路径解析依赖项,就像LoadFrom方法所做的一样

您应该使用LoadFrom方法并从上下文加载,或者,如果可能的话,最好使用Load并加载上下文。

我正在用Assembly.LoadFile(filename)加载它们

这是一个很常见的错误。之所以这样做,是因为只有LoadFile()有一篇像样的MSDN文章,读起来不像官样文章,加载上下文在.NET.中是一个非常抽象的概念

只有当您有意不希望找到依赖程序集时,才应使用LoadFile()。这是非常罕见的,只有像检查程序集这样的程序才会这样做。像反汇编程序这样的工具。

LoadFrom()需要使CLR也在该目录中查找依赖程序集。通常要注意,这并不能保证修复DLL。地狱,类型的标识包括它所来自的程序集。具有相同命名空间名称的类型出现问题,并且类型名称存在于多个程序集中。一种故障模式,在单独的目录中有多组程序集时更可能出现这种故障。尤其是当你不能控制它的内容时,比如插件场景。Mystifying InvalidCastExceptions可能是你的下一个敌人,也是用LoadFile()加载的程序集的一种非常常见的故障模式。程序员喜欢将文件组织到目录中,这有点像OCD,这是一种专业责任,与CLR喜欢避免DLL地狱的方式非常不兼容。如果这是插件场景的要求,那么一定要支持像MEF这样的破旧插件框架,以限制事故的发生。

要指示CLR在Modules''XXX子目录下进行探测,请创建一个新的配置文件使用任何文本编辑器命名为applicationname.exe.config,或使用提供的App.config文件,并将该文件保存在包含applicationname.exe应用程序,在本例中为应用程序。

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Modules'XXX"/>
    </assemblyBinding>
  </runtime>
</configuration>

假设您想使用绝对路径或相对路径(与.exe不在同一目录层次结构中)指定程序集,请使用<codebase>,无论如何,这两种方法都与xml配置文件的使用绑定在一起

Assembly.LoadFrom(…)

确实相当于<codebase>;可以采取相对和绝对路径

主要参考:Pro C#5.0和.net 4.5