转载  (版本策略学习) .NET 项目中引用的DLL 版本不一致的问题

分类: 2015-11-17T11:31:47    1146人阅读   

最近遇到了一个问题,和下面的描述相类似:

 

-- A:

Specific version assembly reference

Apr 23, 2008 07:18 AM|LINK

Good morning to you all!

I'm specifying "Specific version"=false on all my added assembly references but when I try to deploy the solution with an assembly with different version than the referenced I get an exception: "Could not load file or assembly...".

Example:

Project1 with version 1.0.0.0 specified is compiled into Project1.dll

Project2 references Project1.dll with "Copy Local"=true and "Specific version"=false and is compiled into Project2.dll

MyWebApplication references Project2.dll

On deployment of MyWebApplication I replace Project1.dll (which has been copied into the bin-catalog since Project2 references it) with a recompiled Project1.dll withversion 1.1.0.0. This results in the exception mentioned above, telling me that Project1.dll version 1.0.0.0 couldn't be found.

Analyzing Project2.dll with Reflector shows that the version number is included in the reference-string, even though I specified "Specific version"=false. Shouldn't the version number be omitted under this circumstances?

Best regards,

Richard

 

-- B:

 

Re: Specific version assembly reference

Apr 28, 2008 07:32 AM|LINK

 

Hi Richard,

You may have some confusing about the “Specific version” property. “Specific Version” property is only a build-time directive (for Visual Studio). It has no effect on the runtime version resolution of the referenced assembly.

Please check the following link for detailed informaiton.

What you need to know about referenced assemblies in VS2005
http://blogs.msdn.com/irenak/archive/2005/12/13/503105.aspx

 

 

-- A:

 

Re: Specific version assembly reference

Apr 28, 2008 09:30 AM|LINK

Ok, the "Specific version" property only comes in play during compilation. I understand.

I probably should explain my real scenario for you; I'm working on a website that uses the same application layers (DLLs) as a winforms application.

The problem is that the website is hosted on a shared location where a recompiled version of MySQL is required (which is provided by the host and rarely the latest version) since the original won't run under Medium Trust.

I work with / develop the two applications, keeping them in sync with changes, and I want to use the latest version of MySQL in the winforms application and the recompiled version on the website. Since the website uses basic functionality from the MySQL reference the risk of having breaking changes between the versions are slim. The winforms application on the other hand uses the MySQL reference extensively and therefore bugfixes from MySQL is essential.

But I don't want to recompile the whole "tree" with different references each time I make a change. I would like to compile the application layers with the latest version from MySQL and replace the copied DLL with the provided DLL on deployment and let the runtime on the website ignore the fact that the version is incorrect (older).

The application is built in many layers, where the lowest level (assemblies) references the MySQL assembly, kind of like this.

WinForm-application                        Website-application

                              Application.dll

                              Datalayer.dll

                              MySQL.Data.dll


I've read that adding the following section in the web.config might help, but will it work when the reference is indirectly references through many layers of references?

<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="MySql.Data" publicKeyToken="C5687FC88969C44D" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-5.2.1.0" newVersion="5.0.8.1"/> </dependentAssembly> </assemblyBinding> </runtime>

Thanks!

 

 

 

 

在实际工作中,版本策略被使用得比较多,本节将借助分析这个面试题来简要介绍程序集的版本策略和配置方法。
  所涉及到的知识点
  • 版本策略的基本原理
  • 程序集版本策略的配置
  分析问题
  当一个程序集通过名字、版本、文化和公钥进行加载时,CLR允许程序员指定该程序集的哪些版本可以代替目前版本进行加载。这些都是通过版本策略来实现的。所谓的版本策略,就是一个程序集版本的重定向,把加载当前这个版本定向到加载可替代的版本。版本策略可以在以下三个级别上进行配置:
  • 应用程序策略
  • 发行者策略
  • 计算机策略
  这三个级别的版本策略都可以通过XML文件来进行配置。现在笔者来分别介绍。
  1.应用程序策略 
  应用程序策略可以在应用程序配置文件中进行配置,应用程序配置文件位于应用程序目录下。对于.EXE应用程序,其配置文件由exe文件名加上.config后缀名构成,例如一个test.exe的应用程序,其配置文件就是test.exe.config。而对于任何一个Web应用程序来说,其配置文件的文件名都是web.config。
  版本策略都记录在配置文件的assemblyBinding节点下。代码2-7是一个应用程序的配置文件例子,这里只选取了本节所关心的版本策略部分内容。
  代码2-7 VersionStrategy:Web.Config
  <?xml version="1.0"?>
  <configuration>
  <runtime>
  <assemblyBinding>
  <!--对这个程序集进行版本重定向-->
  <dependentAssembly>
  <assemblyIdentity
  name="NET.MST.Second.Compile"
  publicKeyToken="60c29e5f0af3e9bb">
  </assemblyIdentity>
  </dependentAssembly>
  <!--重定向的策略-->
  <bindingRedirect oldversion="0.0.0.0-12.2.2.2"
  newversion="12.3.0.0">
  </bindingRedirect>
  </assemblyBinding>
  </runtime>
  </configuration>
  在代码2-7这个配置文件中,指定了NET.MST.Second.Compile,60c29e5f0af3e9bb这个组件的版本策略,这个策略将0.0.0.0到12.2.2.2之间的所有版本重定向到12.3.0.0版本上。
  2.发行者策略
  发行者策略是针对那些被放入全局程序集缓存(GAC)中的程序集,发行者策略以一个和代码2-6同样格式的配置文件形式绑定到程序集上,被一同放入GAC中。发行者策略配置文件的文件名非常古怪,它是这样的一个字符串:主版本号.次版本号.程序集名.dll。正因为如此,一个程序集的每个主版本/次版本号只能有一个发行者策略。
  3.计算机策略 
  同样地,计算机策略同样由一个配置文件表示,它的格式也和代码2-7基本类似。计算机级版本策略配置文件的文件名为:machine.config,它被存储在%SystemRoot% Microsoft.NET Frameworkv****CONFIG目录下。
  读到这里,读者可能会有这样的疑问:版本策略可以在3个级别进行配置,那这些策略是如何协作的呢?按照.NET的机制,3个级别的版本策略将会按照顺序依次执行,而上一级别的执行结果将会被作为下一级别的执行输入。
  3个级别版本策略被依照:应用程序、发行者、计算机的顺序依次执行。而其中,发行者策略是可选的,在以下两种情况下发行者策略将不会被执行。
  • 程序集没有被加入到GAC中
  • 应用程序策略制定忽略发行者策略
  在第一种情况下,根本就不存在发行者策略配置文件,当然CLR也就不会执行发行者策略。而第二种情况,是程序员在应用程序策略中指定忽略发行者策略,具体做法是在应用程序配置文件中加入publisherPolicy节点,并且把apply属性值设置为no。代码2-8就是在代码2-7的基础上,指定了忽略发行者策略。
  代码2-8 VersionStrategy-NoPolisherPolicy:Web.Config
  <?xml version="1.0"?>
  <configuration>
  <runtime>
  <assemblyBinding>
  <!--对这个程序集进行版本重定向-->
  <dependentAssembly>
  <assemblyIdentity
  name="NET.MST.Second.Compile"
  publicKeyToken="60c29e5f0af3e9bb">
  </assemblyIdentity>
  </dependentAssembly>
  <!--重定向的策略-->
  <bindingRedirect oldversion="0.0.0.0-12.2.2.2"
  newversion="12.3.0.0">
  </bindingRedirect>
  <!--指定忽略发行者策略-->
  <publisherPolicy apply="no">
  </publisherPolicy>
  </assemblyBinding>
  </runtime>
  </configuration>

  答案
  CLR支持在3个级别上设定版本策略,依次是:应用程序策略、发行者策略和计算机策略。所有策略的设置都是通过修改配置文件来实现。3个级别的策略依次会被CLR执行,而上一个策略的执行结果将被作为下一个策略的输入。发行者策略仅仅针对那些放入GAC的程序集,并且可以在应用程序策略中被指定忽略。

分享到: