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

时间:2009-09-25 15:03:39

标签: .net assemblies system.reflection assembly-loading

我正在查看msdn文档,我仍然对加载程序集时使用LoadFileLoadFrom之间的区别有点困惑。有人可以提供一个例子或类比来更好地描述它。 MSDN文档让我更加困惑。此外,ReflectionOnlyLoadFromLoadFrom相同,只是它仅以反射模式加载程序集。

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

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

2)它声明LoadFile不会将文件加载到'LoadFrom上下文'中,并且不会使用加载路径解析依赖关系。这意味着什么,有人可以提供一个例子吗?

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

7 个答案:

答案 0 :(得分:88)

这清楚了吗?

// 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的许多理由,但是如果你需要在同一个程序集的不同副本上使用反射,它就在那里。

答案 1 :(得分:57)

来自Suzanne Cook's blog

  

LoadFile与LoadFrom

     

小心 - 这些不一样   的事情。

     

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

     

LoadFile()根本没有通过Fusion绑定 - 加载器就是这样   提前并正好加载*   来电者要求。它不使用   Load或LoadFrom   上下文。

     

所以,LoadFrom()通常会给你什么   你问过,但不一定。   LoadFile()适合那些真正的,   真正想要的确切要求。   (*但是,从v2开始,政策将会   适用于LoadFrom()和   LoadFile(),所以LoadFile()不会   必然正是如此   请求。另外,从v2开始,如果是   具有身份的装配在   GAC,将使用GAC副本   代替。使用ReflectionOnlyLoadFrom()   加载你想要的 - 但是,   请注意,程序集以这种方式加载   无法执行。)

     

LoadFile()有一个catch。既然如此   它不使用绑定上下文   依赖关系不是自动的   在其目录中找到。如果他们不是   你可以在Load上下文中找到它   必须订阅   AssemblyResolve事件以便绑定   他们。

请参阅here

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

答案 2 :(得分:38)

经过多次头疼之后,我今天下午发现了一个与众不同的地方。

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

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

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

答案 3 :(得分:3)

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

答案 4 :(得分:2)

我注意到的一个区别是:

Assembly.LoadFile - 在具有有限用户权限的不同AppDomain中加载程序集(diffrence principel)。无法进行血清/消毒等手术。

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

答案 5 :(得分:1)

.NET具有不同的加载上下文。 Suzanne Cook在这里写到了他们:http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx

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

答案 6 :(得分:0)

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

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