我有两个程序集:HelloWorld.exe和Hello.dll。 exe是主程序集,主程序集正在使用dll。
我编译了HelloWorld.exe(1.0.0)和Hello.dll(1.0.0)。我将程序集放在不同的文件夹中。
然后我将Hello.dll的版本更改为2.0.0并继续使用2.0.0版本覆盖Hello.dll 1.0.0。然后我启动HelloWorld.exe,它工作正常。
我预计它会崩溃并立即刻录,因为编译EXE时引用的Hello.dll是1.0.0。现在,1.0.0 DLL已被2.0.0取代,但它仍然有效!
根据MSDN:
默认情况下,程序集仅使用完全相同的类型 用它构建和测试的程序集(名称和版本号)。 也就是说,如果您的程序集使用版本1.0.0.2中的类型 另一个程序集,它将(默认情况下)不使用相同的类型 另一个程序集的1.0.0.4版。这个使用名称和 用于识别引用程序集的版本有助于避免“DLL Hell” 升级到一个应用程序破坏其他应用程序的问题。
问题:
请注意,Hello.dll没有强名称。
这是HelloWorld.exe的清单:
// Metadata version: v2.0.50727
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly extern Hello
{
.ver 2:0:0:0
}
.assembly HelloWorld
{
...//snipped
}
这是从Fuslogvw.exe(程序集绑定日志查看器)中获取的程序集绑定日志:
=== Pre-bind state information ===
LOG: User = ian.uy
LOG: DisplayName = Hello, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/Users/ian.uy/Desktop/HelloWorld/HelloWorld/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = NULL
Calling assembly : HelloWorld, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/ian.uy/Desktop/HelloWorld/HelloWorld/bin/Debug/Hello.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Users\ian.uy\Desktop\HelloWorld\HelloWorld\bin\Debug\Hello.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Hello, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Binding succeeds. Returns assembly from C:\Users\ian.uy\Desktop\HelloWorld\HelloWorld\bin\Debug\Hello.dll.
LOG: Assembly is loaded in default load context.
答案 0 :(得分:2)
为什么会这样?
因为你已经指定了;)
如何让它无效?
奖金问题:构建过程中会发生什么?外部依赖项的版本是否硬编码为主依赖项?
除非您指定,否则不会。它默认是关闭的。精心设计的组件应该向后兼容,版本应该不重要。
答案 1 :(得分:1)
我面对同样的事情并试图查看msbuild日志:
msbuild /v:detailed /t:build
以下几行看起来很有趣:
Unified Dependency" Newtonsoft.Json,Version = 8.0.0.0,Culture = neutral, 公钥= 30ad4fe6b2a6aeed&#34 ;. 使用此版本而不是原始版本" 7.0.0.0"在" C:\ src \ BindingTest \ Lib1 \ bin \ Debug \ Lib1.dll"因为AutoUnify是 '真'
此外,如果在构建之后检出生成的app.config文件,您可能会看到app.config最初没有的自动绑定重定向。
所以我们观察到的行为与" automatic assembly unification"和" automatic binding redirection" msbuild进程。
以下是documentation关于AutoUnify
参数的说明:
如果为true,则生成的依赖关系图将自动视为 如果有一个app.Config文件传入AppConfigFile 参数。此虚拟App.Config文件具有bindingRedirect条目 对于每个冲突的程序集集,使得最高版本 选择装配。这样做的结果是永远不会有 关于冲突组件的警告,因为每次冲突都会发生 已经解决了。
如果为true,则每次不同的重新映射都将导致高优先级 评论显示旧版本和新版本以及AutoUnify是否属实。
最后,如果你想观察"失败"你可以用以下参数调用msbuild:
msbuild /v:d /t:build /p:AutoUnifyAssemblyReferences=false;AutoGenerateBindingRedirects=false
答案 2 :(得分:0)
为了版本控制,运行时区分常规程序集和强名称程序集。版本检查仅对强名称程序集进行。
https://docs.microsoft.com/en-us/dotnet/framework/app-domains/assembly-versioning
因此,答案如下