我正在查看 msdn 文档,但我仍然对加载程序集时使用 LoadFile
和 LoadFrom
之间的确切区别感到有些困惑。有人可以提供一个例子或类比来更好地描述它。 MSDN 文档让我更加困惑。此外,ReflectionOnlyLoadFrom
与 LoadFrom
相同,只是它仅在反射模式下加载程序集。
由于我的 .NET 经验不是最好的,这里有一些关于使用 LoadFile 的 MSDN 文档的问题:
1) LoadFile
检查具有相同标识但位于不同路径的程序集是什么意思?身份是什么(例子)?
2) 它指出 LoadFile
不会将文件加载到“LoadFrom Context”中,并且不会使用加载路径解析依赖关系。这是什么意思,有人可以举个例子吗?
3) 最后,它指出 LoadFile
在这种有限的场景中很有用,因为 LoadFrom 无法加载具有相同身份但不同路径的程序集;它只会加载第一个这样的程序集,这又让我想到了同样的问题,程序集的身份是什么?
这清楚了吗?
// 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
的许多理由,但如果您需要在同一程序集的不同副本上使用反射,它就在那里。
LoadFile 与 LoadFrom 小心——它们不是一回事。 LoadFrom() 通过 Fusion,如果已经在 LoadFrom 上下文中加载了一个程序集,则可以将其重定向到不同路径但具有相同标识的另一个程序集。 LoadFile() 根本不通过 Fusion 绑定 - 加载器只是继续并准确地加载*调用者请求的内容。它不使用 Load 或 LoadFrom 上下文。所以, LoadFrom() 通常会给你你所要求的,但不一定。 LoadFile() 适用于那些真正、真正想要确切要求的人。 (*然而,从 v2 开始,策略将同时应用于 LoadFrom() 和 LoadFile(),因此 LoadFile() 不一定是请求的内容。此外,从 v2 开始,如果具有其标识的程序集位于GAC,将使用 GAC 副本。使用 ReflectionOnlyLoadFrom() 准确加载您想要的内容 - 但请注意,以这种方式加载的程序集无法执行。) LoadFile() 有一个问题。由于它不使用绑定上下文,因此不会在其目录中自动找到其依赖项。如果它们在 Load 上下文中不可用,则必须订阅 AssemblyResolve 事件才能绑定到它们。
请参阅here。
另请参阅同一博客上的 Choosing a Binding Context 篇文章。
经过一番摸索,今天下午我自己发现了一个不同之处。
我想在运行时加载一个 DLL,而 DLL 位于另一个目录中。该 DLL 有自己的依赖项 (DLL),它们也位于同一目录中。
LoadFile():加载特定的 DLL,但不加载依赖项。因此,当第一次从 DLL 中调用其他 DLL 时,它会抛出 FileNotFoundException。
LoadFrom():加载我指定的 DLL 以及该目录中的所有依赖项。
.LoadFile
的程序集所引用的程序集中创建一个对象的新实例时,我得到了 FileNotFoundException
。将此更改为 .LoadFrom
似乎可以解决问题,但我不知道为什么!谢谢
LoadFrom
和 LoadFile
是不同的。所以你不能只替换这两个
注意:如果使用 8.3 路径加载一个程序集,然后从非 8.3 路径加载,它们将被视为不同的程序集,即使它们是相同的物理 DLL。
.NET 有不同的加载上下文。苏珊娜库克在这里写了关于他们的文章:https://docs.microsoft.com/en-us/archive/blogs/suzcook/choosing-a-binding-context
这是 .NET 隔离不混淆引用的方式。
我注意到的一个区别是:
Assembly.LoadFile - 在具有有限用户权限的不同 AppDomain 中加载程序集(差异原则)。无法执行序列化/反序列化等操作。
Assembly.LoadFrom- 以相同的用户权限(相同的原则)在相同的 AppDomain 中加载程序集。
在我的例子中,我只需要简单地删除位于@C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files
的 ASP 应用程序缓存。它在站点首次运行时重建。请务必先停止 IIS。
希望这对像我这样的人有所帮助。
不定期副业成功案例分享
string.Compare(x, y) == 0
检查两个字符串引用的值是否相等?我想你想要x == y
在那里?如果出于晦涩的原因您确实需要依赖于文化的相等性检查,例如,写string.Equals(x, y, StringComparison.CurrentCulture)
会更清楚。