在项目的配置文件Web.config中,会看到<runtime>节点,以及包含在其中的<assemblyBinding>节点,这显然与程序集有关,这些节点到底何时被用到呢?

在默认情况下,在运行时,JIT编译器将IL代码编译成本地代码时,会查看IL代码中的字段、局部变量、方法参数等引用了哪些类型,然后借助程序集的TypeRef和AssemblyRef元数据,内部使用System.Reflection.Assembly的Load方法来确定需要被加载的程序集,包括module。

Load方法接收一个代表强类型名称程序集的字符串,类似如下:

Assembly a = Assembly.Load(
    "somename, Version=1.2.3.4" +
    "Culture=neutral, PublicKeyToken=........"
);

a.CreateInstance("someclassname");

在Load方法内部,会使用一个叫做"程序集解析(assembly resolver)"的机制寻找程序集。首先会遵循"版本策略"去寻找程序集合适的版本。这个"版本策略"可以在配置文件中配置。在"C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config"中完成计算机级别的配置,在当前项目的Web.config中完成应用程序级别的配置。例如在Web.config中:

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" />
        <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

如果想取消"版本策略",可以在Web.config中按如下配置:

<runtime>
    <rt:assemblyBinding>
      <rt:publisherPolicy apply="no" />
    </rt:assemblyBinding>
</runtime>

以上,程序集是按需加载的,当程序运行,需要用到某个类型,就加载该类型所在的程序集,把该类型加载到内存中。

如果不想让程序集按需加载,要么把类型设置为静态的,要么直接告诉CLR如何加载程序集。使用System.Reflection.Assembly的静态方法LoadFrom就可以加载固定位置的某个程序集。

举例:创建一个名称为Customer的类库,并创建CustomerBehavior类

using System;

namespace Customer
{
    public class CustomerBehavior
    {
        public void SayHello()
        {
            Console.WriteLine("hello");
        }
    }
}


把Customer类库的生成路径设置为F盘的temp文件夹。在客户端通过LoadFrom动态加载F盘temp文件夹下的Customer.dll程序集。

        static void Main(string[] args)
        {
            Assembly a = Assembly.LoadFrom("f:\\temp\\Customer.dll");
            var type = a.GetType("Customer.CustomerBehavior");
            Console.WriteLine(type.Assembly.FullName);
            Console.ReadKey();
        }

总结:在CLR内部使用System.Reflection.Assembly的Load方法加载程序集,而加载的程序集版本策略可以通过配置文件设置。

CLR如何加载程序集以及程序集版本策略的更多相关文章

  1. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)0-------通过应用程序域AppDomain加载和卸载程序集

    本博客中以“C#.Net 如何动态加载与卸载程序集(.dll或者.exe)”开头的都是引用莫问奴归处 微软装配车的大门似乎只为货物装载敞开大门,却将卸载工人拒之门外.车门的钥匙只有一把,若要获得还需要 ...

  2. 通过应用程序域AppDomain加载和卸载程序集

    微软装配车的大门似乎只为货物装载敞开大门,却将卸载工人拒之门外.车门的钥匙只有一把,若要获得还需要你费一些心思.我在学习Remoting的时候,就遇到一个扰人的问题,就是Remoting为远程对象仅提 ...

  3. 异常:System.BadImageFormatException,未能加载正确的程序集XXX

    IDE:VS2015 语言:C# 异常:System.BadImageFormatException,未能加载正确的程序集XXX或其某一依赖项... 一般是由于目标程序的目标平台与其某一依赖项的目标编 ...

  4. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)3---- 动态加载Assembly应用程序

    下载 supergraphfiles.exe 示例文件. 应用程序体系结构 在我专攻代码之前,我想谈谈我尝试做的事.您可能记得,SuperGraph 让您从函数列表中进行选择.我希望能够在具体的目录中 ...

  5. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)2----通过应用程序域AppDomain加载和卸载程序集之后,如何再返回原来的主程序域

    实现目的:动态加载dll,执行完毕之后可以随时卸载掉,并可以替换这些dll,以在运行中更新dll中的类. 其实就是通过应用程序域AppDomain加载和卸载程序集. 在这方面微软有篇文章http:// ...

  6. 使用C#的AssemblyResolve事件动态解析加载失败的程序集

    我们知道反射是 依赖注入 模式的基础,依赖注入要求只在项目中引用定义接口的程序集,而不引用接口实现类的程序集,因为接口实现类的程序集应该是通过反射来动态加载的,这样才能保证接口与其实现类之间的松耦合. ...

  7. .net加载失败的程序集重新加载

    在.net程序中,程序集是Lazy加载的,只有在用的时候才会去加载,当程序集加载失败时,会触发AppDomain.AssemblyResolve的事件,在这个事件中,我们甚至还可以进行补救,从别得地方 ...

  8. 使用C#的AssemblyResolve事件和TypeResolve事件动态解析加载失败的程序集

    我们知道反射是 依赖注入 模式的基础,依赖注入要求只在项目中引用定义接口的程序集,而不引用接口实现类的程序集,因为接口实现类的程序集应该是通过反射来动态加载的,这样才能保证接口与其实现类之间的松耦合. ...

  9. 异常:System.BadImageFormatException,未能加载正确的程序集XXX或其某一依赖项

    常:System.BadImageFormatException,未能加载正确的程序集XXX或其某一依赖项 看到这个异常,我估计谁都会头大一阵子,不过还好,由于前面知道要设置为x86,加上以前观察过I ...

随机推荐

  1. Linux下内存泄漏工具【转】

    转自:http://www.cnblogs.com/guochaoxxl/p/6970090.html 概述 内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况 ...

  2. git 入门常用命令(转)

    Git工作流程:D:\projects\Setup2\Setup2\Setup2\Express\SingleImage\DiskImages\DISK1 git clone工作开始之初,可通过git ...

  3. ajax与302响应

    在ajax请求中,如果服务器端的响应是302 Found,在ajax的回调函数中能够获取这个状态码吗?能够从Response Headers中得到Location的值进行重定向吗?让我们来一起看看实际 ...

  4. H2内嵌数据库使用步骤

    1.找到h2数据库的jar包 D:\repositories\com\h2database\h2\1.4.187\h2-1.4.187.jar 2.双击jar包,配置连接信息 Driver Class ...

  5. 一个无锁消息队列引发的血案(四)——月:RingQueue(上) 自旋锁

    目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...

  6. 使用 Gradle 对应用进行个性化定制

    啥也不说了,直接进入主题吧.本篇文章主要根据实际开发中遇到的需求,讲解使用 Gradle 对应用的不同版本进行个性化定制. 场景介绍 一般的应用基本上都有正式服和测试服,这个就不需要多说了.但是有些应 ...

  7. PhpStorm,Pycharm,Goland破解

    phpstorm是一个轻量级且便捷的PHP IDE,其旨在提供用户效率,可深刻理解用户的编码,提供智能代码补全,快速导航以及即时错误检查.不但是php开发的利器,前端开发也是毫不逊色的.下面记录Php ...

  8. [USACO17FEB]Why Did the Cow Cross the Road I G

    一开始想写$DP$,发现直接转移完全有后效性 所以本小蒟蒻写了个最短路 每走三步就要吃草是这个题最难搞的地方,我们建图时不妨只对于距离等于三的点连边 考虑完全覆盖所有情况,从一个点走一步,两步,然后三 ...

  9. Codeforces 601C Kleofáš and the n-thlon 概率dp

    Kleofáš and the n-thlon 我们可以用dp算出比当前这个人得分少的概率, 然后人数乘概率就好啦. dp[ i ][ j ]表示进行了 i 轮 得分为 j 的概率, 因为每个人都是独 ...

  10. hibernate Validator 6.X 的学习,bean的约束(主要包括的是容器元素的验证)

    1. 四:案例二(property的验证) 1.