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


126

我查看了msdn文档,但对使用LoadFileLoadFrom加载程序集之间的区别到底还是有些困惑。有人可以提供示例或类比来更好地描述它吗?MSDN文档使我更加困惑。此外,ReflectionOnlyLoadFrom与相同,LoadFrom只是它仅以反射模式加载装配件。

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

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

2)声明LoadFile不将文件加载到“ LoadFrom Context”中,并且不使用加载路径解析依赖项。这意味着什么,有人可以提供示例吗?

3)最后,它指出LoadFile在有限的情况下很有用,因为LoadFrom无法加载具有相同标识但路径不同的程序集;它只会加载第一个这样的程序集,这又使我想到一个问题,程序集的身份是什么?


10
我也认真地认为有时MS应该雇用更好的作家或其他人,因为句子并不总是可以理解的……
Tarik 2012年

7
另请参见非文献资料
Panic Panic

1
@ColonelPanic MS可以说所有内容都已记录在案……但是帮助因素为零。
传说

Answers:


96

这样可以清除吗?

// 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

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

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


2
CodeBase与身份相同吗?
Xaisoft

不,我只是在这里使用CodeBase作为程序集的任意属性,以说明第二个Assembly实例指向“错误”文件(在第一个示例中)。我正在用更多详细信息更新我的答案。
Jeff Sternal

1
它清除了一下,但是当使用LoadFrom和使用LoadFile时,path1和path2如何指向磁盘上同一程序集的不同副本,path1和path2指向不同程序集。什么是路径1和路径2的示例?谢谢你的耐心。
Xaisoft

为什么要检查两个字符串引用的值相等string.Compare(x, y) == 0?我想你想x == y在那里吗?如果出于晦涩的原因,您确实希望进行与文化相关的相等性检查,那么编写起来就更清楚了string.Equals(x, y, StringComparison.CurrentCulture)
Jeppe Stig Nielsen 2014年

@JeffSternal的“ Suzanne Cook on Assembly Identity”上的链接似乎在这里坏了……
Martin Verjans,2016年

61

来自Suzanne Cook的博客

LoadFile与LoadFrom

小心-这些不是同一回事。

LoadFrom()通过Fusion,可以重定向到其他路径下的另一个程序集,但如果已经在LoadFrom上下文中加载了同一组件,则具有相同的标识。

LoadFile()根本不会通过Fusion进行绑定-加载程序仅继续进行并完全加载*调用者请求的内容。它不使用Load或LoadFrom上下文。

因此,LoadFrom()通常会为您提供所需的内容,但不一定如此。LoadFile()适用于那些确实非常想要确切的请求的人。(*但是,从v2开始,策略将同时应用于LoadFrom()和LoadFile(),因此LoadFile()不一定正是所要求的。而且,从v2开始,如果具有其标识的程序集位于GAC,将改用GAC副本。请使用ReflectionOnlyLoadFrom()完全加载所需的内容-但是请注意,无法以这种方式加载程序集。)

LoadFile()有一个陷阱。由于它不使用绑定上下文,因此不会在其目录中自动找到其依赖项。如果它们在Load上下文中不可用,则必须订阅AssemblyResolve事件才能绑定到它们。

这里

另请参阅选择绑定上下文同一博客上的“文章。


谢谢,我将检查博客,更新了有关msdn文档的一些问题。
Xaisoft

@Xaisoft-苏珊·库克(Suzanne Cook)的博客再次回答了“装配体身份”。参见blogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx。它本质上是一个“程序集显示名称”,类似于:“系统,版本= 1.0.3300.0,文化=中性,PublicKeyToken = b77a5c561934e089”,因此既包括程序集的实际名称,也包括版本号以及其他标识信息(例如PublicKeyToken等)。
CraigTP

1
当谈到融合时,她指的是什么?
Xaisoft

1
的确,杰夫(Jeff)是当场。请参阅此链接:grimes.demon.co.uk/workshops/fusionWS.htm,以获取有关Fusion子系统及其在.NET中加载程序集的技术的不错的教程
CraigTP

1
只是一个快速更新,请注意上面(grimes.demon.co.uk/workshops/fusionWS.htm)的URL不再有效,现在已经转移到:richardgrimes.com/workshops/fusionWS.htm
CraigTP

45

经过反复的努力,今天下午我自己发现了一个不同之处。

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

LoadFile():加载特定的DLL,但不加载依赖项。因此,当第一次从DLL内部对其他DLL中的一个进行调用时,它引发了FileNotFoundException。

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


4
那正是我的问题!FileNotFoundException当创建一个新对象的实例时,我得到了,该实例是由我刚刚加载的程序集引用的程序集中定义的.LoadFile。将其更改为.LoadFrom似乎可以解决此问题,但我不知道为什么!谢谢
Connell 2013年

1
谢谢,我遇到了同样的问题。
Ivandro IG Jao

4

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



0

我注意到的一个区别是:

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

Assembly.LoadFrom-以相同的用户权限(相同的原理)将装配加载到同一AppDomain中。


3
这是不正确的。是什么让您相信Assembly.LoadFile将程序集加载到另一个AppDomain中?
fr34kyn01535

0

就我而言,我只需要删除位于@的ASP应用程序缓存即可 C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files。站点首次运行时将对其进行重建。确保首先停止IIS。

希望这对像我这样的人有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.