第一节:程序集加载

我们知道JIT编译器将方法的IL代码编译成本地代码时,会查看IL代码中引用了哪些类型。在运行时,JIT编译器利用程序集的TypeRef和AssemblyRef元数据表来确定哪一个程序集定义了所引用的类型。在AssemblyRef元数据表的记录项中,包含了构成程序集强名称的各个部分。JIT编译器获取所有这些部分,包括名称(无扩展名和路径)、版本、语言文化和公钥标记,并把它连接成一个字符串。然后,JIT编译器尝试将与该标识匹配的一个程序集加载到AppDomain中(如果还没有加载的话)。如果被加载的程序集时弱命名的,那么标识中只包含程序集的名称(不包含版本、语言文化以及公钥标记信息)。

在内部,CLR使用System.Reflection.Assembly类的静态方法Load来尝试加载这个程序集。这个方法在.NET Framework SDK文档中是公开的,可调用它显式的将一个程序集加载到AppDomain中。这个方法是CLR中的与Win 32 LoadLibrary函数等价的方法。Assembly的Load方法实际上有几个重载版本。以下是最常用的重载版本的原型:

public static Assembly Load(AssemblyName assemblyRef);

public static Assembly Load(string assemblyString);

在内部,Load导致CLR向程序集应用一个版本绑定重定向策略,并在GAC(全局程序集缓存)中查找程序集。如果没找到,就接着去应用程序的基目录、私有路径子目录和codebase位置查找。如果调用Load时,传递时一个弱命名程序集,Load就不会向程序集应用一个版本绑定重定向策略,CLR也不会去GAC中查找程序集。如果Load找到程序集,会返回对代表已加载的那个程序集的一个Assembly对象的引用。如果Load没有找到指定的程序集,会抛出一个System.IO.FileNotFoundException。

重要提示:一些开发人员可能注意到,System.AppDomain提供了一个Load方法。和Assembly的Load方法不同,AppDomain的Load是一个实例方法,它允许将一个程序集加载到一个指定的AppDomain中。该方法设计供非托管代码调用,允许宿主将一个程序集”注入”到一个AppDomain中。托管代码的开发人员一般情况下不应调用它,因为在调用AppDomain的Load方法时,需要向它传递一个标识了程序集的字符串,该方法随后会应用策略,并在一些常规位置搜索一些程序集。我们知道,AppDomain关联了一些告诉CLR如何查找程序集的设置。为了加载这个程序集,CLR将使用与指定AppDomain关联的设置,而不是与发出调用的那个AppDomain关联的设置。

然后,AppDomain的Load方法会返回对程序集的一个引用System.Reflection.Assembly不是从MarshalByRefObject派生的,所以程序集对象必须按值封送回发出调用的那个AppDomain.但是,现在CLR就会用发出调用的那个AppDomain的设置来定位并加载程序集。如果使用发出调用的那个AppDomain的策略和搜索位置没有找到指定的程序集,就会抛出一个FileNotFoundException。这个行为一般不是你所期望的,应该避免使用AppDomain的Load方法。

在大多数动态可扩展的应用程序中,Assembly的Load时程序集加载到AppDomain的首选方式。但是,它要求你实现掌握构成程序集标识的各个部分。开发人员经常要写一些工具和实用程序,以便在程序集上执行一些处理。这些工具的例子包含:ILDasm.exe,PEVerify.exe,CorFlags.exe,GACUtil.exe, Sgen.exe,SN.exe,XSD.exe等,所有这些工具都要获取引用一个程序集文件的路径名(包括文件扩展名)的命令行实参。为了以指定路径名的的方式加载一个程序集,要调用Assembly的LoadForm方法。在内部,LoadForm首先会调用System.Reflection.AssemblyName类的静态方法GetAssemblyName,该方法打开指定的文件,查找AssemblyRef元数据表的记录项,提取程序集标识信息,然后以一个System.Reflection.AssemblyName对象的形式返回这些信息(文件同时会关闭)。随后,LoadForm方法在内部调用Assembly的Load方法,将AssemblyName对象传给他。然后,CLR会应用版本绑定重定向策略,并在各个位置查找匹配的程序集,如果Load找到匹配的程序集,就会加载它,并返回代表已加载一个程序集的对象Assembly,LoadForm将返回这个值。如果Load没有找到匹配的程序集,LoadForm就会加载通过LoadForm实参传递的路径中的程序集。当然,如果以加载了一个具有相同标识的程序集,LoadFrom方法会简单的返回代表已加载程序集的一个Assembly对象。

VS的UI设计人员和其他工具一般用的是Assembly的LoadFile方法。这个方法可以从任何路径加载一个程序集,并可将具有相同标识的一个程序集多次加载到一个AppDomain中。在设计器/工具中对应用程序的UI进行了修改,CLR不会自动解析任何依懒性问题;你的代码必须向AppDomain的AssemblyResolve事件登记,并让事件回调方法显示地加载任何依赖的程序集。

如果你构建的一个工具只是通过反射来分析程序集的元数据,并希望确保程序集中的任何代码都不会执行,那么加载程序集的最佳方式就是使用Assembly的ReflectionOnlyLoadFrom 或者ReflectionOnlyLoad方法。

ReflectionOnlyLoadFrom方法将加载由路径指定的文件;文件的强名称标识不会获取,也不会在GAC和其他位置搜索。ReflectionOnlyLoad方法会在GAC、应用程序基目录、私有路径和codebase指定的位置搜索指定的程序集。但是,和Load方法不同的是,ReflectionOnlyLoad不会应用版本控制策略,所以你指定了哪个版本,获得的就是哪个版本。如果要自行为一个程序集标识指定版本控制策略,可以将字符串传给AppDomain的ApplyPolicy方法。

ReflectionOnlyLoadFrom 或者ReflectionOnlyLoad方法加载程序集时,CLR禁止程序集中的任何代码执行,试图执行由这两个方法加载的程序集中的代码,会导致CLR抛出一个异常,这两个方法允许工具加载延迟签名的程序集,这种程序集正常情况下会因为安全权限不够而无法加载。另外,这种程序集也可能是为不同的CPU架构而创建的。

利用反射来分析由这两个方法之一加载的程序集时,代码经常需要向AppDomain的ReflectionOnlyAssemblyResovle事件注册一个回调方法,以便手动加载任何引用的程序集;CLR不会自动帮你做这个事情,回调方法被调用时,它必须调用Assembly的ReflectionOnlyLoadFrom或ReflectionOnlyLoad方法,以便显示加载一个程序集,并返回对程序集的一个引用。

许多应用程序都由一个要依赖于众多DLL文件的EXE文件组成。部署这个应用程序时,所有文件都必须部署。然后,有一个技术允许只部署一个EXE文件。首先,标识出EXE文件要依赖的、同时不是作为.NET FRAMEWORK本身的一部分发布的所有DLL文件,将这些DLL添加到你的VS项目中,对于添加的这些DLL,有显示它的属性,并将它的“生成操作”更改为”嵌入的资源”。这回导致C#编译器将DLL文件嵌入EXE文件中,以后只需部署这个EXE文件即可。

在运行时,CLR会找不到依赖的DLL程序集,为了解决这个问题,应用程序初始化时,向AppDomain的ResolveAssembly事件登记一个回调方法,

 

 

            AppDomain.CurrentDomain.AssemblyResolve += (sender, arg) =>{String resourceName = "AssemblyLoadingAndReflection:" + new AssemblyName(arg.Name) + ".dll";using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)){Byte[] assemblyData = new Byte[stream.Length];stream.Read(assemblyData, 0, assemblyData.Length);return Assembly.Load(assemblyData);}};

  

现在一个线程首次调用一个方法时,如果发现该方法引用了依赖的DLL文件中的一个类型,就会引发一个ResolveAssembly事件,而上诉回调代码会找到所需的嵌入的DLL资源,并调用Assembly的Load方法重载版本,从而加载所需的资源。

 

转载于:https://www.cnblogs.com/bingbinggui/p/4573487.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398009.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS系统根目录组织结构

对于linux运维初学者来说,认识linux系统的文件组织结构来说,也是一件非常有意义的事情。当然对于学习运维者来说首选的Centos系列linux服务器版本了,同样属于菜鸟的我,今天和大家分享一下当前最为成熟的Centos6.8和Centos7.2版本的…

Sql Server 部署SSIS包完成远程数据传输

本篇介绍如何使用SSIS和作业完成自动更新目标数据任务。 ** 温馨提示:如需转载本文,请注明内容出处。** 本文链接:https://www.cnblogs.com/grom/p/9018978.html 笔者需要定期从服务器更新N家客户的远程服务器数据,上一篇的存储过程是其中一…

java值类型和引用类型 == 比较,Java中值类型和引用类型的比较与问题解决

一、问题描述前几天因为一个需求出现了Bug。说高级点也挺高级,说白点也很简单。其实也就是一个很简单的Java基础入门时候的值类型和引用类型的区别。只是开发的时候由于自己的问题,导致小问题的出现。还好突然想起来以前看过一篇对于该问题讲解的博客&am…

java 泛型的几点备忘

1、在java虚拟机中是没有泛型的&#xff0c;所有泛型类的参数都会被擦除&#xff0c;如下&#xff1a; public void test(List<String> list, int num){}public void test(List<Integer> list, int num){} 这两个方法对于java编译器来说是一样的&#xff0c;因此无…

用最简单的例子说明设计模式(三)之责任链、建造者、适配器、代理模式、享元模式...

责任链模式一个请求有多个对象来处理&#xff0c;这些对象是一条链&#xff0c;但具体由哪个对象来处理&#xff0c;根据条件判断来确定&#xff0c;如果不能处理会传递给该链中的下一个对象&#xff0c;直到有对象处理它为止使用场景1)有多个对象可以处理同一个请求&#xff0…

Ubuntu 12.04 修改/etc/resolv.conf重启后还原成修改前状态解决办法

$ sudo vi /etc/resolvconf/resolv.conf.d/head (最后一行添加)按a或i进入编辑模式search spreadtrum.com (寻找或声明域spreadtrum.com)nameserver 10.0.0.97按Esc键退出编辑模式:wq (保存并退出)$ sudo resolvconf -u (更新resolv.conf文件)/etc/resolv.conf文件中就会多…

利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)...

最近看老罗的视频&#xff0c;跟着完成了利用Java操作MySQL数据库的一个框架类JdbcUtils.java,完成对数据库的增删改查。其中查询这块&#xff0c;包括普通的查询和利用反射完成的查询&#xff0c;主要包括以下几个函数接口: 1、public Connection getConnection() 获得数据库…

Linux启动提示Kernel panic - not syncing: Attempted to kill init解决办法

系统类型&#xff1a;CentOS 6.5(x64) 启动提示&#xff1a;Kernel panic - not syncing: Attempted to kill init 解决办法&#xff1a; 系统启动的时候&#xff0c;按下‘e’键进入grub编辑界面&#xff0c;编辑grub菜单&#xff0c;选择“kernel /vmlinuz-XXXXro root/dev/v…

vuex和vuejs

前言&#xff1a;在最近学习 Vue.js 的时候&#xff0c;看到国外一篇讲述了如何使用 Vue.js 和 Vuex 来构建一个简单笔记的单页应用的文章。感觉收获挺多&#xff0c;自己在它的例子的基础上进行了一些优化和自定义功能&#xff0c;在这里和大家分享下学习心得。 在这篇教程中我…

laravel mysql 配置,laravel5数据库配置及其注意事项

今天分享一个Laravel5数据库配置上的坑。Laravel5作为一套简洁、优雅的PHP Web开发框架(笑)&#xff0c;唯一不足的一点就是中文手册或者说是资料比较少&#xff0c;虽然现在很多大神也开始普及这些东西&#xff0c;但是大神一遍也会忽略一下小坑。今天配置了一下数据库&#x…

React开发中常用的工具集锦

本文从属于笔者的React入门与最佳实践系列。本文记录了笔者在React开发中常见的一些工具插件&#xff0c;如果你想寻找合适的项目生成器或者模板&#xff0c;请参考笔者的使用Facebook的create-react-app快速构建React开发环境 React Devtools React Devtools是React官方提供的…

9-[记录操作]--数据的增删改,权限管理

1、数据操作语言&#xff1a; DML&#xff08;data manage language&#xff09; 在MySQL管理软件中&#xff0c;可以通过SQL语句中的DML语言来实现数据的操作&#xff0c;包括 使用INSERT实现数据的插入UPDATE实现数据的更新使用DELETE实现数据的删除使用SELECT查询数据以及。…

hdu 1023 Train Problem II

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid1212 Train Problem II Description As we all know the Train Problem I, the boss of the Ignatius Train Station want to know if all the trains come in strict-increasing order, how many orders that all the tra…

阿贝尔分部求和法的应用(二)

14.(阿贝耳定理) 设$\sum\limits_{n0}^{\infty}a_{n}s$. 则$\lim_{x\to 1-}\sum\limits_{n0}^{\infty}a_{n}x^{n}s$.证明: 容易看出$f(x)\sum\limits_{n0}^{\infty}a_{n}x^{n}$在$0 \leq x \leq 1$上一致收敛.由Cauchy收敛准则知,任意$\varepsilon>0$,存在$n$任意$p>0$有…

python中字母大小顺序,如何在Python中按字母顺序对unicode字符串排序?

Python sorts by byte value by default, which means comes after z and other equally funny things. What is the best way to sort alphabetically in Python?Is there a library for this? I couldnt find anything. Preferrably sorting should have language support…

Nginx自建CDN加速节点 实现DNS智能解析网站项目

如今&#xff0c;网站项目越来越多的会使用CDN加速&#xff0c;如果需要便捷一点的可以直接用第三方提供的CDN加速服务&#xff0c;比如百度CDN、七牛、又拍云、腾讯云、阿里云等等服务商都有提供这类服务。但是前提条件是需要一定的成本&#xff0c;以及网站域名是需要BA才可以…

字符串字典排序

把字符串以字典的展示形式排序&#xff0c;如把字符串abc,bad,aade,bdca排列成aade,abc,bad,bdca。 1.使用冒泡排序 (1) 相邻两数据两两比较&#xff0c;较大的放到后面&#xff0c;直到把最大的字符串放在最后一个位置。 (2) 从头开始再进行相邻数据两两比较&#xff0c;较大的…

OC2_点语法(属性关键字)

// // Dog.h // OC2_点语法(属性关键字) // // Created by zhangxueming on 15/6/16. // Copyright (c) 2015年 zhangxueming. All rights reserved. //#import <Foundation/Foundation.h>interface Dog : NSObject //属性关键字 //assgin(缺省)直接赋值 //基本类型 …

matlab中获取view,ios 怎么获取一个view的位置

ios 怎么获取一个view的位置以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;ios 怎么获取一个view的位置打开appstore进入应用&#xff0c;右上角的分享按钮(从右往左数第二个)&#xff0c;拷…

eureka需要替换吗_Spring Cloud Alibaba迁移指南1:零代码从Eureka迁移到Nacos

作者&#xff1a;得少&#xff0c;校对&#xff1a;周立。在本号首发&#xff0c;欢迎转载。Spring Cloud官方宣布Spring Cloud Netflix进入维护状态&#xff0c;后续不再会有新的功能已成为事实。作为开发者&#xff0c;如何使用极简的方式替换Netflix相关组件成为首要解决的问…