【问题标题】:Why instances created with Activator.CreateInstance do not resolve references?为什么使用 Activator.CreateInstance 创建的实例不解析引用?
【发布时间】:2013-07-18 13:43:03
【问题描述】:

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

Application\Modules\XXX

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

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

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

TProvider 有一个方法可以返回在另一个程序集中定义的类(也存储在 XXX 中)。在调用必须加载引用的 providerInstance 的该方法时,我收到了一个 FileNotFoundException,即即使依赖项位于同一个 XXX 文件夹中,也找不到依赖程序集。

查看融合日志,程序集加载器仅检查 Application 文件夹,而不是 XXX ...

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

谢谢。

【问题讨论】:

  • 程序集加载和您创建对象实例的方式彼此无关。 <probing privatePath="Modules\XXX"/> 应该可以帮到你。
  • @Dennis:有些依赖只有在调用 providerInstance 的某些方法时才能解决。如果 providerInstance 的方法将返回在另一个程序集上定义的类,则该类将仅在第一次调用该方法时才被解析。如果我使用 ActivatorInstance 创建实例,它会失败。如果我正常创建它,它可以工作。
  • @Dennis:我不应该需要它,因为所有程序集都位于同一个文件夹中。
  • 我认为,您误解了程序集加载和解析机制。你如何获得providerType?通过Assembly.Load/LoadFrom然后通过类型枚举?
  • @Dennis:我正在使用 Assembly.LoadFile(filename) 加载它们,然后搜索一些特定类型,是的。

标签: c# .net dependencies .net-assembly fusion


【解决方案1】:

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

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

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

LoadFrom() 需要让 CLR 在该目录中查找依赖程序集。一般来说,请注意这不是 DLL Hell 的保证修复,类型的标识包括它来自的程序集。具有相同命名空间名称的类型出现问题,并且类型名称存在于多个程序集中。一种故障模式,在单独目录中的程序集组中更有可能发生故障。尤其是当您不控制其内容时,例如插件场景。神秘的 InvalidCastExceptions 可能是您的下一个克星,这也是使用 LoadFile() 加载的程序集的一种非常常见的故障模式。程序员喜欢将文件组织到目录中,这有点强迫症,这是一种职业责任,并且与 CLR 喜欢避免 DLL Hell 的方式完全不兼容。如果这是插件方案的要求,那么请使用 MEF 之类的成熟插件框架来限制故障。

【讨论】:

  • 谢谢汉斯。我们所有的开发都在 XXX 文件夹中,因为我们在一个使用 PRISM 应用程序的大团队中工作,我们的责任在 XXX 文件夹中开始和结束。那么当你被限制在一个文件夹中时,可能不会发生 DLL 地狱。
【解决方案2】:

要指示 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 不在同一目录层次结构中),请改用&lt;codebase&gt;,无论如何这两种方法都与 xml 配置文件的使用有关。

Assembly.LoadFrom(...)

确实是&lt;codebase&gt; 等价的;可以采用相对路径和绝对路径

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

【讨论】:

    【解决方案3】:

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

    LoadFile 不会将文件加载到 LoadFrom 上下文中,并且 不会 使用加载路径解决依赖关系,就像 LoadFrom 方法一样

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-25
      • 2015-10-14
      • 1970-01-01
      • 2021-08-12
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 2020-03-11
      相关资源
      最近更新 更多