.NET通过包含版本号的强名称共享程序集的模型,解决的DLL hell的问题,但是在某种情况下这种模型却存在一个缺陷;
假设一个开发者因为修改了Bug而重新发布了一个新版本号的共享程序集,并假设这个新版本的共享程序集与旧版本的完全兼容,并且它的旧版本也安装在GAC中,这样虽然我们部署了新的版本,但是新版本不会被使用,因为在应用程序中以硬编码的方式写入了要调用的共享程序集的版本号,在这种情况下,我们该如何处理呢?
微软为我们提供了一种解决方案,就是使用发布者策略程序集,使用发布者策略程序集后,一个应用程序集请求的版本号为3.3.0.0,但他最终可能使用的却是3.3.1.0的版本的该共享程序集,因为该共享程序集所关联的发布者策略程序集包含了3.3.0.0到3.3.1.0的重新定向信息。
那么什么是发布者策略程序集呢?他只是一个配置文件,一个发布者策略程序集由两个模块组成,一个模块是一个以.congfig为后缀名并包含发布者重定向信息的XML配置文件;另一个模块只包含一个清单,该模块使用al.exe工具构造的。
XML配置文件如下:
Foo2.config
使用al.exe生成只包含清单的模块的方法:
al.exe /out:policy.1.0.Foo2.dll /version:1.0.0.0 /keyfile:MyKey.snk /linkresource:Foo2.config
解释一下:
/out指定包含清单的模块的名称,该名称必须通过使用特定的规则来构成:
policy向CLR指出,这里使用一个发布者策略做为生成策略;
1.0向CLR指出,该发布者策略将自己应用于请求1.0版本的Foo2.dll,这里仅设定主版本号和次版本号;
Foo2告诉CLR该策略将应用于名为Foo2.dll的程序集。
/version 应用于发布者策略本身而不是Foo2.dll。
/keyfile 这里的keyfile必须与Foo2.dll使用的keyfile一致,以此向CLR证明发布者策略确实来自于与Foo2.dll相同的发布者,并且发布者策略程序集需要保存在GAC中所以必须拥有一个强名称,也就是必须通过keyfile签名。
/linkresource制定了包含发布者策略重定向信息的XML配置文件的名称,由于这个选项,Foo2.config才变成了发布者策略程序集中的一个模块,具体来说,Foo2.dll并不是在物理上包含在policy.1.0.Foo2.dll模块中,而是在逻辑上数据policy.1.0.Foo2程序集。
另外,重新定向是由CLR完成的,在执行期间,是由CLR负责定位并装在程序集的,因此在定位程序集是CLR会将发布者策略纳入它的考虑范围。
一个发布者策略程序集只关注一个单独的程序集,而一个程序集可有有多个发布者策略程序集,而只有版本号最新的发布者策略程序集才会被采用,
针对某个特定的使用共享程序集的应用程序,用户可以指定CLR忽略发布者策略程序集(这一点将在后面的文章中详细介绍)