我的假设始终是CLR加载了应用程序域启动时所需的所有DLL.但是,我写了一个让我质疑这个假设的例子.我启动我的应用程序并检查加载了多少个模块.
Process[] ObjModulesList;
ProcessModuleCollection ObjModulesOrig;
//Get all modules inside the process
ObjModulesList = Process.GetProcessesByName("MyProcessName");
// Populate the module collection.
ObjModulesOrig = ObjModulesList[0].Modules;
Console.WriteLine(ObjModulesOrig.Count.ToString());
Run Code Online (Sandbox Code Playgroud)
然后我重复完全相同的代码,我的计数是不同的.附加DLL是C:\ WINNT\system32\version.dll.
我真的很困惑为什么计数会有所不同.
有人可以详细说明CLR正在做什么以及它如何加载这些东西,以及它正在做什么逻辑?
Cha*_*ana 24
以下复制自Don Box的优秀Essential .Net.(可在此处获得)
(并且,imho,任何专业.Net开发人员必备的)
CLR Loader
CLR Loader负责加载和初始化程序集,模块,资源和类型.CLR加载程序加载并初始化尽可能少的内容.与Win32加载程序不同,CLR加载程序不会解析并自动加载从属模块(或程序集).相反,只有在实际需要时才会按需加载从属部分(与Visual C++ 6.0的延迟加载功能一样).这不仅可以加快程序初始化时间,还可以减少正在运行的程序所消耗的资源量.在CLR中,加载通常由基于类型的即时(JIT)编译器触发.当JIT编译器尝试将方法体从CIL转换为机器代码时,它需要访问声明类型的类型定义以及类型字段的类型定义.此外,JIT编译器还需要访问由JIT编译的方法的任何局部变量或参数使用的类型定义.加载类型意味着加载程序集和包含类型定义的模块.这种按需加载类型(和程序集和模块)的策略意味着程序中未使用的部分永远不会被带入内存.这也意味着正在运行的应用程序通常会看到随着时间的推移加载的新程序集和模块,因为在执行期间需要这些文件中包含的类型.如果这不是您想要的行为,您有两种选择.一种是简单地声明要与加载器交互的类型的隐藏静态字段.加载类型意味着加载程序集和包含类型定义的模块.这种按需加载类型(和程序集和模块)的策略意味着程序中未使用的部分永远不会被带入内存.这也意味着正在运行的应用程序通常会看到随着时间的推移加载的新程序集和模块,因为在执行期间需要这些文件中包含的类型.如果这不是您想要的行为,您有两种选择.一种是简单地声明要与加载器交互的类型的隐藏静态字段.加载类型意味着加载程序集和包含类型定义的模块.这种按需加载类型(和程序集和模块)的策略意味着程序中未使用的部分永远不会被带入内存.这也意味着正在运行的应用程序通常会看到随着时间的推移加载的新程序集和模块,因为在执行期间需要这些文件中包含的类型.如果这不是您想要的行为,您有两种选择.一种是简单地声明要与加载器交互的类型的隐藏静态字段.这也意味着正在运行的应用程序通常会看到随着时间的推移加载的新程序集和模块,因为在执行期间需要这些文件中包含的类型.如果这不是您想要的行为,您有两种选择.一种是简单地声明要与加载器交互的类型的隐藏静态字段.这也意味着正在运行的应用程序通常会看到随着时间的推移加载的新程序集和模块,因为在执行期间需要这些文件中包含的类型.如果这不是您想要的行为,您有两种选择.一种是简单地声明要与加载器交互的类型的隐藏静态字段.
加载程序通常代表您隐式执行其工作.开发人员可以通过程序集加载器显式地与加载器进行交互.程序集加载程序通过类上的LoadFrom
静态方法向开发人员公开System.Reflection.Assembly
.此方法接受CODEBASE字符串,该字符串可以是文件系统路径,也可以是标识包含程序集清单的模块的统一资源定位符(URL).如果找不到指定的文件,加载程序将抛出System.FileNotFoundException
异常.如果可以找到指定的文件但不是包含程序集清单的CLR模块,则加载程序将抛出System.BadImageFormatException
异常.最后,如果CODEBASE是使用其他方案的URL file:
,则调用方必须具有WebPermission访问权限,否则System.SecurityException
抛出异常.此外,具有非协议的URL的程序集在file:
加载之前首先下载到下载缓存.
清单2.2显示了一个简单的C#程序,它加载位于的程序集file://C:/usr/bin/xyzzy.dll
,然后创建一个名为的包含类型的实例AcmeCorp.LOB.Customer
.在此示例中,调用者提供的所有内容都是程序集的物理位置.当程序以这种方式使用程序集加载程序时,CLR会忽略程序集的四部分名称,包括其版本号.
示例2. 2.使用显式CODEBASE加载程序集
using System;
using System.Reflection;
public class Utilities {
public static Object LoadCustomerType() {
Assembly a = Assembly.LoadFrom(
"file: //C:/usr/bin/xyzzy. dll") ;
return a.CreateInstance("AcmeCorp.LOB.Customer") ;
}
}
Run Code Online (Sandbox Code Playgroud)
虽然按位置加载程序集有点令人感兴趣,但大多数程序集都是使用程序集解析程序按名称加载的.程序集解析程序使用四部分程序集名称来确定使用程序集加载程序将哪个基础文件加载到内存中.如图2.9所示,此名称到位置解析过程考虑了多种因素,包括托管应用程序的目录,版本控制策略和其他配置详细信息(所有这些都将在本章后面讨论).
程序集解析器通过类的Load
方法向开发人员公开System.Reflection.Assembly
.如清单2.3所示,此方法接受四部分程序集名称(作为字符串或AssemblyName引用),并且表面上看起来类似于程序集加载程序公开的LoadFrom方法.相似性只是皮肤深层,因为Load方法首先使用程序集解析器使用相当复杂的一系列操作来查找合适的文件.第一个操作是应用版本策略以确定应该加载所需程序集的确切版本.
例2.3.使用装配解析器装载装配
using System;
using System.Reflection;
public class Utilities {
public static Object LoadCustomerType() {
Assembly a = Assembly.Load(
"xyzzy, Version=1. 2. 3.4, " +
"Culture=neutral, PublicKeyToken=9a33f27632997fcc") ;
return a.CreateInstance("AcmeCorp.LOB.Customer") ;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
11855 次 |
最近记录: |