我可以将6.2和5.8安装到GAC中,但我希望这个项目可以进行xcopy部署。我相信.NET会在应用程序bin目录中搜索程序集,如下所示: \bin\conflict.dll(6.2) \bin\5.8\conflict.dll(5.8)
但此时,如何在项目中添加对两个版本的conflict.dll的引用,然后如何确保旧的conflict.dll部署到\bin\5.8?我需要创建一个构建操作,还是有其他方法?
谢谢。
经过多个小时的搜寻与咒骂,我找到了一个解决方案,它易于实现并且可靠。
问题 就像所有其他答案指出的一样,必须满足以下所有条件:
解决方案 如下所示,步骤如下:
在您的解决方案目录下创建一个目录,例如 lib\
,其中包含以下层次结构:
lib\Conflict\v1\Conflict.dll
lib\Conflict\v2\Conflict.dll
将以下内容添加到您的 app/web.config
文件中:
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Conflict" publicKeyToken="111111111111" /> <codeBase version="1.0.0.0" href="bin\Conflict\v1\Conflict.dll" /> <codeBase version="2.0.0.0" href="bin\Conflict\v2\Conflict.dll" /> </dependentAssembly> </assemblyBinding> </runtime>
添加一个后构建事件,使用
xcopy
命令:xcopy $(SolutionDir)\lib $(TargetDir) /Y /S
构建一次,以便复制文件。点击“项目->显示所有文件”。右键单击
bin\Conflict
,选择包含在项目中
(这样可以避免在代码中进行操作)。如果要打包Web应用程序,则必须这样做才能部署文件。完成!
我认为 .net 会在应用程序 bin 目录中搜索程序集,例如:\bin\conflict.dll (6.2) \bin\5.8\conflict.dll (5.8)
不,这是错误的。我建议您阅读这篇文章以了解 CLR 使用何种启发式方法进行探测。heuristics does the CLR use for probing。
话虽如此,您不能在同一个应用程序域中加载相同程序集的两个不同版本,您可以将同一程序集的不同版本加载到同一个应用程序域中,但这被认为是considered bad practice,应该避免。在您的情况下,这意味着您必须选择要使用的冲突程序集的版本。您有几个选择:
helper.dll
to use the latest version of conflict.dll
(I will definetely go with this one if Ihave the source code for helper.dll
).Choose which version of conflict.dll
you want and apply a <bindingRedirect>
in your config file. For example if you want to use the latest version:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="conflict"
publicKeyToken="xxxxxxxxx"
culture="neutral" />
<bindingRedirect oldVersion="5.8.0.0"
newVersion="6.2.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
helper.dll
的引用时加载版本6.2的conflict.dll
。请注意,如果这两个版本使用不同的密钥进行强签名,此技术将无法使用。显然,由于helper.dll
已经编译成5.8版,如果存在任何差异(缺少方法、不同的方法签名),则调用冲突方法时会导致运行时异常,因此只有在确定自己在做什么时才能这样做。
结论:无论选择哪种路径,您都需要在bin文件夹中复制一个版本的conflict.dll
。
Assembly.LoadFrom
从两个不同位置加载相同的程序集-然后调用AppDomain.CurrentDomain.GetAssemblies()
。 - Andras ZoltanClassLibrary1.dll和ClassLibary1vanything.dll是同名且公钥相同的程序集的v1.0.0.0和v2.0.0.0版本。尽管classlibrary1vanything.dll文件名错误,但它仍然可以工作(可能是因为它已签名)。
在app.config中,我放了一个codebase提示,并认为这就是它能够工作的原因(最初我将其部署为不同的文件名),但后来我将其注释掉了,它仍然可以工作。当程序集必须部署到子文件夹或完全不同的位置时,codebase可能是最有用的。
原始文本
我尝试让MS支持文章中提到的第二个选项之一起作用,但似乎不想要。
毫无疑问,有一些聪明的方法可以直接完成它,但由于我还没有找到(而且不够聪明),所以我会使用上述支持主题中显示的第三个选项并连接到应用程序域的AssemblyResolve
事件。
如果您添加了自己的配置(可能只是在appSettings中),以便将程序集的完整名称绑定到不同的文件名,则在AssemblyResolve事件处理程序中,您可以查看要加载的程序集的名称,以查看它是否在您的配置中。 如果是,则获取位置并使用Assembly.LoadFrom进行加载。
因此,一旦您有了这样的设置,您只需在其中添加Conflict v5.8程序集名称的条目以及应用程序应使用的文件名即可。
我不知道您部署的是什么类型的应用程序,但在win forms、控制台应用程序和服务中,AppDomain.CurrentDomain.BaseDirectory
将等于bin文件夹,您可以将其与要加载的文件名连接起来。网站有点棘手。
应该能很好地工作。