LoadFile 和 LoadFrom 与 .NET 程序集的区别?

Posted

技术标签:

【中文标题】LoadFile 和 LoadFrom 与 .NET 程序集的区别?【英文标题】:Difference between LoadFile and LoadFrom with .NET Assemblies? 【发布时间】:2010-12-01 11:03:27 【问题描述】:

我查看了 msdn 文档,但对于在加载程序集时使用 LoadFileLoadFrom 之间到底有什么区别,我仍然有些困惑。有人可以提供一个例子或类比来更好地描述它。 MSDN 文档让我更加困惑。另外,ReflectionOnlyLoadFrom 是否与 LoadFrom 相同,只是它仅在反射模式下加载程序集。

由于我的 .NET 经验不是最好的,这里有一些关于使用 LoadFile 的 MSDN 文档的问题:

1) LoadFile 检查具有相同标识但位于不同路径的程序集是什么意思?身份是什么(例子)?

2) 它指出LoadFile 不会将文件加载到“LoadFrom Context”中,并且不会使用加载路径解析依赖关系。这是什么意思,谁能举个例子?

3) 最后,它指出LoadFile 在这种有限的场景中很有用,因为 LoadFrom 无法加载具有相同身份但路径不同的程序集;它只会加载第一个这样的程序集,这又给我带来了同样的问题,程序集的身份是什么?

【问题讨论】:

说真的,我也认为有时 MS 应该聘请更好的作家或其他人,因为句子并不总是可以理解的...... 另见undocumentation @ColonelPanic MS 可以说所有内容都已记录在案......但有一个帮助因素 zeroooo。 【参考方案1】:

这样就解决了吗?

// path1 and path2 point to different copies of the same assembly on disk:

Assembly assembly1 = Assembly.LoadFrom(path1);
Assembly assembly2 = Assembly.LoadFrom(path2);

// These both point to the assembly from path1, so this is true
Console.WriteLine(assembly1.CodeBase == assembly2.CodeBase);

assembly1 = Assembly.LoadFile(path1);
assembly2 = Assembly.LoadFile(path2);

// These point to different assemblies now, so this is false
Console.WriteLine(assembly1.CodeBase == assembly2.CodeBase);

编辑:要回答您在修改后的问题中提出的问题,您一定要阅读Suzanne Cook on Assembly Identity。

有很多规则可以控制程序集的加载方式,其中一些规则与它们如何解决依赖关系有关 - 如果您的 AssemblyA 依赖于 AssemblyB,.NET 应该在哪里查找 AssemblyB?在全局程序集缓存中,它找到 AssemblyA 的同一目录,还是完全在其他地方?此外,如果它找到该程序集的多个副本,它应该如何选择使用哪一个?

LoadFrom 有一组规则,而LoadFile 有另一组规则。很难想象有很多使用 LoadFile 的理由,但是如果您需要在同一个程序集的不同副本上使用反射,它就在那里。

【讨论】:

CodeBase和Identity一样吗? 不,我只是在这里使用 CodeBase 作为程序集的任意属性来说明第二个 Assembly 实例指向“错误”文件(在第一个示例中)。我正在用更多细节更新我的答案。 它清除了一点,但是当使用LoadFrom和使用LoadFile时,path1和path2如何指向磁盘上同一程序集的不同副本,path1和path2指向不同的程序集。什么是 path1 和 path2 的示例?感谢您的耐心等待。 为什么要检查两个字符串引用的值是否与string.Compare(x, y) == 0 相等?我想你想要x == y 吗?如果出于晦涩的原因您确实需要依赖于文化的相等性检查,例如写string.Equals(x, y, StringComparison.CurrentCulture) 会更清楚。 @JeffSternal Link on "Suzanne Cook on Assembly Identity" 似乎在这里被破坏了......【参考方案2】:

来自Suzanne Cook's blog:

LoadFile 与 LoadFrom

小心 - 这些不一样 东西。

LoadFrom() 通过 Fusion 并可以重定向到另一个 组装在不同的路径,但 如果一个人已经是相同的身份 在 LoadFrom 上下文中加载。

LoadFile() 根本不通过 Fusion 绑定 - 加载器只是运行 提前并准确加载* 来电者请求。它不使用 Load 或 LoadFrom 上下文。

所以,LoadFrom() 通常会给你什么 你要求,但不一定。 LoadFile() 是为那些真正, 真的想要确切的要求。 (*但是,从 v2 开始,政策将 应用于 LoadFrom() 和 LoadFile(),所以 LoadFile() 不会 一定是 请求。此外,从 v2 开始,如果 大会以其身份在 GAC,将使用 GAC 副本 反而。使用 ReflectionOnlyLoadFrom() 准确加载您想要的内容 - 但是, 请注意,以这种方式加载的程序集 无法执行。)

LoadFile() 有一个问题。既然它 不使用绑定上下文,它的 依赖不是自动的 在其目录中找到。如果他们不是 在加载上下文中可用,您 必须订阅 AssemblyResolve 事件以绑定 给他们。

见here。

另请参阅同一博客上的 Choosing a Binding Context 文章。

【讨论】:

谢谢,我会看看博客,我更新了我的帖子,提出了一些关于 msdn 文档的问题。 @Xaisoft - Suzanne Cook 的博客再次提供了 Assemblies Identity 的答案。见blogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx。它本质上是一个“程序集显示名称”,类似于:“System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”因此包括程序集的实际名称、版本号以及其他标识信息(如PublicKeyToken 等)。 她在谈到 Fusion 时指的是什么? 确实,杰夫是正确的。请参阅此链接:grimes.demon.co.uk/workshops/fusionWS.htm 以获取有关 Fusion 子系统及其在 .NET 中加载程序集的技术的精彩教程 只是一个快速更新,请注意上面的 URL (grimes.demon.co.uk/workshops/fusionWS.htm) 不再有效,现在已移至:richardgrimes.com/workshops/fusionWS.htm【参考方案3】:

经过一番折腾,今天下午我自己发现了不同之处。

我想在运行时加载一个 DLL,而 DLL 位于另一个目录中。该 DLL 有自己的依赖项 (DLL),它们也位于同一目录中。

LoadFile():加载特定的 DLL,但不加载依赖项。因此,当第一次从 DLL 中调用其他 DLL 时,它会抛出 FileNotFoundException。

LoadFrom():加载我指定的 DLL 以及该目录中的所有依赖项。

【讨论】:

这正是我的问题!在我刚刚加载.LoadFile 的程序集引用的程序集中创建一个对象的新实例时,我得到了FileNotFoundException。将其更改为.LoadFrom 似乎可以解决问题,但我不知道为什么!谢谢 谢谢,我也遇到了同样的问题。【参考方案4】:

注意:如果使用 8.3 路径加载一个程序集,然后从非 8.3 路径加载,它们将被视为不同的程序集,即使它们是相同的物理 DLL。

【讨论】:

【参考方案5】:

.NET 有不同的加载上下文。苏珊娜库克在这里写了他们:https://docs.microsoft.com/en-us/archive/blogs/suzcook/choosing-a-binding-context

这是 .NET 隔离不混淆引用的方式。

【讨论】:

【参考方案6】:

我注意到的一个区别是:

Assembly.LoadFile - 将程序集加载到具有有限用户权限的不同 AppDomain 中(差异原则)。无法执行序列化/反序列化等操作。

Assembly.LoadFrom- 在具有相同用户权限(相同原则)的同一个 AppDomain 中加载程序集。

【讨论】:

这是不正确的。是什么让您相信 Assembly.LoadFile 将程序集加载到另一个 AppDomain 中?【参考方案7】:

就我而言,我只需要简单地删除位于@C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files 的ASP 应用程序缓存。它在站点首次运行时重建。请务必先停止 IIS。

希望这可以帮助像我一样的人。

【讨论】:

以上是关于LoadFile 和 LoadFrom 与 .NET 程序集的区别?的主要内容,如果未能解决你的问题,请参考以下文章

20181112_反射基础_对象获取

LoadFrom 和上下文

从内存而不是磁盘加载.NET程序集[关闭]

Lua与C/C++之我最初对于luaL_loadfile的一个误解

Lua与C/C++之我最初对于luaL_loadfile的一个误解

Firebase Auth State Persistence ELECTRON loadFILE vs loadURL