首页 > 代码库 > C#程序集系列13,如何让CLR选择不同版本的程序集

C#程序集系列13,如何让CLR选择不同版本的程序集


本篇主要体验,在存在多个版本程序集的情况下,如何让CLR选择哪个版本程序集运行,以及程序集版本的切换。

 

 

  分别生成非强名称程序集不同版本

□ 生成某个版本的程序集

→清理F盘as文件夹,剩下如下文件
94

→查看Cow.cs文件

using System;
using System.Reflection;
[assembly: AssemblyVersion("3.3.3.3")]
public class Cow
{
    public static void Moo()
    {
        Console.WriteLine("Moo version 1");
    }
}


→编译Cow.cs,生成Farm.dll程序集
95
注意:Farm.dll还不是强名称程序集
→编译MainClass.cs文件,生成可执行文件,引用Farm.dll
96
→运行MainClass.exe
97

 

□ 生成另一个版本的程序集

→修改Cow.cs文件,保存

using System;
using System.Reflection;
[assembly: AssemblyVersion("8.8.8.8")]
public class Cow
{
    public static void Moo()
    {
        Console.WriteLine("Moo version 2");
    }
}

→重新编译Cow.cs,重新生成Farm.dll
98
→再次运行MainClass.exe
99
第二次生成的Farm.dll已经生效。

→修改Cow.cs中的类名为BigCow,保存

using System;
using System.Reflection;
[assembly: AssemblyVersion("8.8.8.8")]
public class BigCow
{
    public static void Moo()
    {
        Console.WriteLine("Moo version 2");
    }
}

→MainClass.cs中的内容如下

using System;
class MainClass
{
    static void Main()
    {
        Cow.Moo();
    }
}

→再次编译Cow.cs,再次生成Farm.dll
100
→再次运行MainClass.exe,发现报错了
101
因为在MainClass.cs中,视图找Cow,但已经不存在,已经变成了BigCow。


 

  分别生成强名称程序集不同版本

□ 生成强名称的程序集

→删除Farm.dll和MainClass.exe
102
→再次把Cow.cs修改为如下,保存

using System;
using System.Reflection;
[assembly: AssemblyVersion("3.3.3.3")]
public class Cow
{
    public static void Moo()
    {
        Console.WriteLine("Moo version 1");
    }
}

→重新编译Cow.cs,这次使用密匙
103
→再次编译MainClass.cs
104
→再次运行MainClass.exe
105

 

□ 生成强名称的另外一个程序集

→修改Cow.cs如下,改变版本和方法实现

using System;
using System.Reflection;
[assembly: AssemblyVersion("8.8.8.8")]
public class Cow
{
    public static void Moo()
    {
        Console.WriteLine("Moo version 2");
    }
}

→再次编译Cow.cs,但用以上次同样的密匙
106
→运行MainClass.exe,报错
107
说明主程序不能找到第一个版本的强名称程序集。

 

  不同强名称程序集版本共存

□ 创建某个版本的强名称程序集

→创建一个Farm文件夹
108
→再次修改Cow.cs,修改成第一个版本,保存

using System;
using System.Reflection;
[assembly: AssemblyVersion("3.3.3.3")]
public class Cow
{
    public static void Moo()
    {
        Console.WriteLine("Moo version 1");
    }
}

→编译Cow.cs,重新生成Farm.dll
109
→运行MainClass.exe
110
说明,当程序集变成第一个版本的强名称程序集,程序又可以正常运行。
→把Farm.dll移动到Farm文件夹中
111
→运行MainClass.exe,因为已经在MainClass.exe.config中自定义了CLR运行时查找程序集的方式,所以运行正常
112

 

□ 创建另一个版本的强名称程序集

→再次修改Cow.cs到第二个版本,保存

using System;
using System.Reflection;
[assembly: AssemblyVersion("8.8.8.8")]
public class Cow
{
    public static void Moo()
    {
        Console.WriteLine("Moo version 2");
    }
}


→编译Cow.cs
113
注意:此时,在Farm文件中还有一个Farm.dll,是第一个版本。
→运行MainClass.exe,再次报错
114
现在的问题是:有2个版本的Farm.dll,CLR运行时无法决定采用哪个版本的Farm.dll.不过,可以先记下这里的PublicKeyToken:863de8402b3a9978

 

  告诉CLR执行哪个版本的强名称程序集

现在同时有了2个Farm.dll,如何让CLR决定指定哪个版本呢?
--需要在MainClass.exe.config中设置

 

→假设,我们需要使用Farm文件夹中的Farm.dll程序集,设置如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="Farm" publicKeyToken="863de8402b3a9978" />
                <bindingRedirect oldVersion="3.3.3.3" newVersion="8.8.8.8" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

→再次运行MainClass.exe
115
一切正常。

 

  使用旧版本的强名称程序集

→修改MainClass.exe.config中设置如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="Farm" publicKeyToken="863de8402b3a9978" />
                <bindingRedirect oldVersion="8.8.8.8" newVersion="3.3.3.3" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

→把as文件夹下的Farm.dll删除,把as下的Farm文件夹中的Farm.dll移动到as下
→再次运行MainClass.exe
116
一切正常,已经在使用旧版本的强名称程序集

 

总结:
○ 如果想让CLR选择哪个版本的程序集运行,该程序集必须是强名称程序集
○ 版本的切换在"可执行文件名称.exe.config"中设置

 

“C#程序集系列”包括:

  C#程序集系列01,用记事本编写C#,IL代码,用DOS命令编译程序集,运行程序

  C#程序集系列02,使用记事本查看可执行程序集的IL代码

  C#程序集系列03,引用多个module

  C#程序集系列04,在程序集包含多个module的场景下理解关键字internal

  C#程序集系列05,让程序集包含多个module

  C#程序集系列06,程序集清单,EXE和DLL的区别

  C#程序集系列07,篡改程序集

  C#程序集系列08,设置程序集版本

  C#程序集系列09,程序集签名

  C#程序集系列10,强名称程序集

  C#程序集系列11,全局程序集缓存

  C#程序集系列12,C#编译器和CLR如何找寻程序集

  C#程序集系列13,如何让CLR选择不同版本的程序集

 

参考资料:

http://www.computersciencevideos.org/  created by Jamie King

 

 

 

C#程序集系列13,如何让CLR选择不同版本的程序集