博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
框架升级后某个类型所在程序集发生转移,应用还能正常运行吗?
阅读量:5943 次
发布时间:2019-06-19

本文共 2254 字,大约阅读时间需要 7 分钟。

所谓类型转移(Type Forwarding)就是将定义在某个程序集中的类型转移到另一个程序集中。我们先通过一个简单的实例让读者朋友们对类型转移有一个感官上的认识。我们利用Visual Studio创建一个针对.NET Framework 3.5的控制台应用,并编写如下一端简单的程序输出两个常用的类型(Function<T>和TimeZoneInfo)所在程序集的名称。现在我们直接运行这个程序,会在控制台上得到如下所示的输出结果,可以看出.NET Framework 3.5(CLR 2.0)环境下的这两个类型定义在程序集System.Core.dll中。

1: public class Program
2: {
3:     static void Main(string[] args)
4:     {
5:         Console.WriteLine(typeof(Func<>).Assembly.FullName);
6:         Console.WriteLine(typeof(TimeZoneInfo).Assembly.FullName);
7:     }
8: }

输出结果:

现在我们对该程序的配置文件(App.config)作如下的修改,其目的在于采用CLR 4.0来运行该程序。再次运行该程序集之后,我们会在控制台上得到不一样的输出结果。通过如下所示的输出结果我们可以看出当.NET Framework从3.5升级到4.0的时候,将原本定义在程序集System.Core.dll中的部分类型转移到了程序集mscorelib.dll之中。

1: 
2:   
3:     
4:   
5: 

输出结果:

跨程序集之间的类型转移帮助框架或者类库的提供者解决这样的难题:某个类型在框架1.0版本的时候定义在程序集A中,当升级到2.0的时候被转移到了程序集B中,使用旧版本的应用可以在不做任何修改的情况下直接对使用的升级后的框架程序集。类型转移需要使用到一个特殊的特性TypeForwardedToAttribute,我们现在通过一个简单的实例来演示如何利用这个特性来解决框架或者类库升级过程在类型跨程序集转移的问题。

这个演示的场景如上图所示:代表应用的App.exe在编译的时候引用了代表框架的程序集Lib.dll,具体使用的是定义其中的类型Foobar,框架进行升级之后新增了一个程序集Lib2.dll,原来定义在Lib.dll中的类型Foobar被转移到了Lib2.dll中。充分利用CLR针对类型转移的支持,我们只需要直接部署新版本的Lib.dll(不包含类型Foobar)和Lib2.dll,现有的程序能够照常运行。

我们利用Visual Studio创建了如上图所示的解决方案。类库项目Lib1代表版本1.0的框架,我们将编译生成的程序集名称设置成Lib,并在其中定义了一个类型Foobar。控制台应用直接应用Lib1,并与其中编写了如下一段简单的程序,其目的在于确认类型Foobar所在的程序集。

1: class Program
2: {
3:     static void Main(string[] args)
4:     {
5:         Console.WriteLine(typeof(Foobar).AssemblyQualifiedName);
6:         Console.Read();
7:     }
8: }
类库项目Lib2和Lib3编译生成代表框架升级之后的两个程序集,我们通过修改项目属性将目标程序集名称设置成Lib和Lib2,Lib2具有针对Lib3的项目引用。我们在Lib3中重新定义了代表被转移的类型Foobar,而Lib2实际上是一个空的项目。要体现类型Foobar从Lib.dll转移到Lib2.dll,我们需要在Lib2项目上应用如下所示的一个
TypeForwardedToAttribute特性(定义在AssemblyInfo.cs中)。
1: [assembly:TypeForwardedTo(typeof(Foobar))]

现在我们对整个解决方案进行编译,然后定位到控制台App项目编译后的输出目录(app\bin\debug),并将项目Lib1编译生成的程序集Lib.dll删除,而将Lib2和Lib3编译生成的程序集Lib.dll和Lib2.dll拷贝到该目录下。现在我们直接运行App.exe,我们会在控制台上得到如下所示的输出结果。

如果某个项目应用了TypeForwardedToAttribute特性指向定义在另一个程序集中的被转出类型,类型转移相关的信息会体现在编译生成的元数据中。就我们的实例而言,项目Lib2编译的生成的程序集通过如下的元数据来指向被转移出去的类型所在的目标程序集。

1: .class extern forwarder Lib.Foobar
2: {
3:   .assembly extern Lib2
4: }

当App.exe被执行的时候,由于元数据体现的依然是针对程序集Lib.dll的引用,所以CLR依然会试图从该程序集中加载类型Foobar。但是通过分析程序集Lib.dll的元数据,CLR知道Foobar已经被转移到程序集Lib2.dll中,所以定义在其中的同名类型Foobar最终会被加载。

转载地址:http://cfwxx.baihongyu.com/

你可能感兴趣的文章
DotNetBar的使用—(界面风格)
查看>>
2.3系列系统中不支持SimpleDateFormat作字段被序列化
查看>>
DJANGO MODEL FORMSETS IN DETAIL AND THEIR ADVANCED USAGE
查看>>
ADO.NET复习——自己编写SqlHelper类
查看>>
库函数strlen源码重现及注意问题
查看>>
《实例化需求》读书笔记
查看>>
常用Java8语法小结
查看>>
ZJOI2019 Day2 游记
查看>>
ccf题库中2015年12月2号消除类游戏
查看>>
WinForm窗体间如何传值
查看>>
Ado.Net 连接数据库
查看>>
java多线程系列1:Sychronized关键字
查看>>
解释性的语言vs编译性语言
查看>>
20155222 2016-2017-2 《Java程序设计》第10周学习总结
查看>>
MapReduce1.x与MapReduce2.x差异
查看>>
PHP array_key_exists() 函数(判断某个数组中是否存在指定的 key)
查看>>
Charpter5 软件测试总结
查看>>
python中@staticmethod、@classmethod和实例方法
查看>>
Java创建数组的三种方法
查看>>
管理计算机内存
查看>>