Load ContextCLR 探测
目录
背景Load ContextCLR 探测过程弱签名程序集的探测过程强签名程序集的探测过程Default ContextLoad-From ContextNo ContextRelfection-Only Context参考资料备注
背景返回目录
任何一门语言都要了解其类型加载过程,如:Java 的 Class Loader,NodeJS 的搜索方式等,本文概述一下我对 CLR 如何加载程序集,重点说一下 Load Context。
其编译时只是在程序集中生成了元数据(如:依赖的程序集标识)和代码。当代码执行时,CLR 会根据元数据加载依赖的程序集。
Load Context返回目录
参考文章:http://msdn.microsoft.com/en-us/library/dd153782(v=vs.110).aspx。
Assembly 会被加载到三个 Load Context 中的任意一个,或者没有在任何上下文中,这三个 Load Context 的名字叫:Default Context、Load-From Context 和 Relfection-Only Context,另外一个没有在任何上下文,可以叫:No Context。
每一个 Load Context 都有自己加载依赖程序集的规则,在解释每个 Load Context 解析依赖的规则之前,先看一下 CLR 的探测过程。
CLR 探测过程返回目录
弱签名程序集的探测过程返回目录
代码
1 Console.WriteLine(Type.GetType("B.ClassB, B"));
文化中立程序集的探测优先级
1 BaseDirectory\B.dll
2 BaseDirectory\B\B.dll
3 BaseDirectory\B.exe
4 BaseDirectory\B\B.exe
文化相关程序集的探测优先级
1 BaseDirectory\zh-CN\B.dll
2 BaseDirectory\B\zh-CN\B.dll
3 BaseDirectory\zh-CN\B.exe
4 BaseDirectory\B\zh-CN\B.exe
使用 probing 指定 privatePath

1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <startup>
4 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
5 </startup>
6 <runtime>
7 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
8 <probing privatePath="B_" />
9 </assemblyBinding>
10 </runtime>
11 </configuration>

指定 privatePath 后的程序集探测优先级

1 BaseDirectory\B.dll
2 BaseDirectory\B\B.dll
3 BaseDirectory\_B\B.dll
4 BaseDirectory\_B\B\B.dll
5 BaseDirectory\B.exe
6 BaseDirectory\B\B.exe
7 BaseDirectory\_B\B.exe
8 BaseDirectory\_B\B\B.exe

注:pirvatePath 只能定义为 BaseDirectory 的子目录。
注:上例只是列出了文化中立程序集的探测优先级,文化相关程序集的探测优先级应该不难猜测出来。
注:也可以使用 codeBase 配置元素来指定探测的子目录,这里就不介绍了。
强签名程序集的探测过程返回目录
强签名程序集会先探测 GAC,如果在 GAC 中没有找到,就按照弱签名程序集的探测过程执行探测。
注:在探测之前 CLR 会根据应用程序配置文件、发布者策略文件和全局配置文件中的配置获取重定向后的版本,然后使用这个重定向后的版本执行探测。
注:强签名程序集的 codeBase 可以指定任意目录(包括 Web 地址)。
Default Context返回目录
使用探测过程加载的程序集都会加载在 Default Context 中,Default Context 中的程序集具备如下特点:
- 依赖的程序集会使用探测过程被自动加载到 DefaultContext。
- 只包含探测过程可以探测到的程序集。
- 其它 Load Context 加载的程序集对于探测过程是不可用的。
Load-From Context返回目录
使用 Assembly.LoadFrom 或 Assembly.Load 的某些重载方法加载的程序集时,如果参数使用了基于路径的形式,而非基于标识的形式,那么加载的程序集会加载在 Load-From Context 中。
Load-From Context 中的程序集具备如下特点:
- 如果 Load-From Context 中已经包含了要加载的程序集(标识相同),就不会加载两次,即使两次加载的路径不同,下面的例子输出的数值是一样的:
1 Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\G_\G.dll");
2 PrintAssemlyCount();
3 Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\G__\G.dll");
4 PrintAssemlyCount(); - Load-From Context 中的程序集对于探测过程是不可用的,下面的例子输出为 null:
1 Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\G_\G.dll");
2 Console.WriteLine(Type.GetType("G.ClassG, G"));
3注:G.DLL 不要在探测路径上。
- Load-From Context 和 Default Context(或者其它Context)都可以同时加载相同标识的程序集,但是程序集内的类型已经不是相同的类型了(虽然内容一样 ),如下例输出为 false:
1 var ass = Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\G_\G.dll");
2 Console.WriteLine(Type.GetType("G.ClassG, G") == ass.GetTypes().First(x => x.Name == "ClassG"));注:G.DLL 不要在探测路径上。
- 依赖的程序集会自动加载,可以从 Default Context 加载,也可以从 Load-Form Context 维护的 Path 下加载,算法后面单独分析,见下例:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace H
8 {
9 public class ClassH
10 {
11 public ClassH()
12 {
13 Console.WriteLine("自动加载A:" + Type.GetType("A.ClassA, A").Assembly.Location);
14 Console.WriteLine("自动加载I:" + Type.GetType("I.ClassI, I").Assembly.Location);
15 }
16 }
17 }在 Main 中执行如下代码:
1 var hAss = Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\H\bin\Debug\H.dll");
2
3 Activator.CreateInstance(hAss.GetTypes().First(x => x.Name == "ClassH"));注:上例中 ClassH 依赖的两个类型都得到正常的加载了。
Load-From Context 中的程序集的依赖程序集的加载算法如下:
注:依赖的程序集的依赖的程序集的算法同上。
No Context返回目录
通过 Assembly.LoadFile 或 Assembly.Load(byte[]) 形式加载的程序集会加载在 No Context 中,No Context 中的程序集具备如下特点:
- 依赖的程序集会自动加载,只会从 Default Context 加载,可以监听这个事件:AppDomain.CurrentDomain.AssemblyResolve,在事件监听器里手工加载其它依赖。
下面这个例子会出现异常:1 Assembly
2 .LoadFile(@"E:\Coding\HappyStudy\LoadContextStudy\Test\bin\Debug\Plugs\Implements\1.0.0.0\Contracts.dll");
3 var operatorType = Assembly
4 .LoadFile(@"E:\Coding\HappyStudy\LoadContextStudy\Test\bin\Debug\Plugs\Implements\1.0.0.0\Implements.dll")
5 .GetTypes()
6 .First(x => x.Name == "Operator");
7 var operatorInstance = Activator.CreateInstance(operatorType);注:Implements.dll 依赖 Contracts.dll。如果 Contracts.dll 包含在探测路径中,则程序会正常执行,不过会加载两个 Contracts.dll。
- 只要路径不同,会返回多个相同程序集标识的程序集实例,如下例:
1 Assembly.LoadFile(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\F_\F.dll");
2 PrintAssemlyCount();
3 Assembly.LoadFile(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\F__\F.dll");
4 PrintAssemlyCount();
Relfection-Only Context返回目录
只有开发工具是才会用到,这里就不介绍了。
参考资料返回目录
- Programming with Application Domains and Assemblies。
- How the Runtime Locates Assemblies。
- Best Practices for Assembly Loading。
备注返回目录
说了挺多的,有啥用处呢?其实 Load Context + AppDomain.CurrentDomain.AssemblyResolve 可以模拟 Java 的 ClassLoader,也可以进一步的模拟 OSGI,下篇文章写个简单的 Demo,不过微软不推荐用这种方式,推荐使用 AppDomain。
Load ContextCLR 探测的更多相关文章
- [转]C#反射-Assembly.Load、LoadFrom与LoadFile进阶
关于.NET中的反射,常用的有三个方法: Assembly.Load()Assembly.LoadFrom()Assembly.LoadFile() 下面说说这三个方法的区别和一些细节问题 1. As ...
- 使用Modernizr探测HTML5/CSS3新特性(转载)
转载地址:http://www.cnblogs.com/TomXu/archive/2011/11/18/detecting-html5-css3-features-using-modernizr.h ...
- 用Nikto探测一个网站所用到的技术
Nikto是一款开源的(GPL)网页服务器扫描器,它可以对网页服务器进行全面的多种扫描,包含超过3300种有潜在危险的文件/CGIs:超过 625种服务器版本:超过230种特定服务器问题,包括多种有潜 ...
- 使用Modernizr探测HTML5/CSS3新特性
[转] HTML5, CSS3以及相关技术(例如canvas和web sockets)带来了非常有用的特性,可以让我们的web程序提升一个新的level.这些新技术允许我们只用HTML,CSS和Jav ...
- C#中的反射 Assembly.Load() Assembly.LoadFrom()
一些关于C#反射的知识,估计也就最多达到使用API的程度,至于要深入了解,以现在的水平估计很难做到,所以下面此篇文章,以作为一个阶段的总结. 对于反射的总结,我想从以下几个方面展开,首先是反射程序集, ...
- [原创]利用Browser协议探测内网主机操作系统版本(无需端口无视防火墙)
利用Browser协议可获取机器IP.MAC.机器名.操作系统.域,如图 浏览 在SMB协议中,计算机为了访问网络资源,就需要了解网络上存在的资源列表(例如在Windows下使用网络邻居查看可以访问的 ...
- Azure Load Balancer : 简介
Azure 提供的负载均衡服务叫 Load Balancer,它工作在 ISO 七层模型的第四层,通过分析 IP 层及传输层(TCP/UDP)的流量实现基于 "IP + 端口" 的 ...
- C#反射-Assembly.Load、LoadFrom与LoadFile
反射Demo: public class Person { public int Age; public void SayHello() { Console.WriteLine("Hello ...
- .NET:鲜为人知的 “Load Context”
背景 任何一门语言都要了解其类型加载过程,如:Java 的 Class Loader,NodeJS 的搜索方式等,本文概述一下我对 CLR 如何加载程序集,重点说一下 Load Context. 其编 ...
随机推荐
- 利用css新属性appearance优化select下拉框
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- jquery选择器基础知识
$("#myELement") 选择id值等于myElement的元素,id值不能重复在文档中只能有一个id值是myElement所以得到的是唯一的元素 $("di ...
- 收藏的一些javascript片段
原文:收藏的一些javascript片段 学习js也很有一段时间,收集了一些js的片段.特地整理排版了一下,以一个js初学者的视界来分析注释了这些代码段,暂且不去讨论它的性能和优化问题,相信会对一些初 ...
- shell 中用管道模拟多线程
shell 中用管道模拟多线程 这里以两个例子来对比多线程和单进程 单线程的例子 # config.txt在这个例子和多线程的例子中都会用到 [root@ns_10.2.1.242 test]$ ca ...
- oracle_面试题01
完成下列操作,写出相应的SQL语句 创建表空间neuspace,数据文件命名为neudata.dbf,存放在d:\data目录下,文件大小为200MB,设为自动增长,增量5MB,文件最大为500MB. ...
- HDU2586
最近的共同祖先反复问的问题. #include <iostream> #include <algorithm> #include <vector> #include ...
- 启用IIS7报错功能
进入:控制面板 - 卸载程序 - 打开或关闭Windows功能 如果访问任何不存在页面或页面出错时空白: Internet 信息服务 - 万维网服务 - 常见 HTTP 功能 - HTTP 错误 打勾 ...
- Team City的安装1
持续集成工具 Team City的安装 前两个月很大一部分精力投入在做部门的持续集成,从概念的了解和工具的选型,再到安装,部署,操作,到最后的真实项目持续集成应用的上线,写了一份手册,包括安装,配置, ...
- Socket 学习(三).5 UDP 的弱点
前面 讲到了,udp 传输文本的例子,发现 udp 确实 比tcp 高效一些,现在我用来传输文件,问题果然来了,结果发现 他不能一次 传输大于 64K的东西! 那么 我自然想到了 切包,多次发送,再合 ...
- 用HMM(隐马)图解三国杀的于吉“质疑”
·背景 最近乘闲暇之余初探了HMM(隐马尔科夫模型),觉得还有点意思,但是网上的教程都超级枯草,可读性很差,抄来抄去的,一堆公式仍在你面前,谁能搞的懂(但园内的两篇写的还算不错.真才实学).在熬制3天 ...