网站空间单位,微信app下载链接,丹东抖音seo精英,潮州有没有做网站的人本文转自#xff1a;https://www.cnblogs.com/zagelover/articles/2726034.html Assembly.Load() Load()方法接收一个String或AssemblyName类型作为参数#xff0c;这个参数实际上是需要加载的程序集的强名称#xff08;名称#xff0c;版本#xff0c;语言#xff0c;公…本文转自https://www.cnblogs.com/zagelover/articles/2726034.html Assembly.Load() Load()方法接收一个String或AssemblyName类型作为参数这个参数实际上是需要加载的程序集的强名称名称版本语言公钥标记。例如.NET 2.0中的FileIOPermission类它的强名称是System.Security.Permissions.FileIOPermission, mscorlib, Version2.0.0.0, Cultureneutral, PublicKeyTokenb77a5c561934e089对于弱命名的程序集则只会有程序集名称而不会有版本语言和公钥标记。如 TestClassLibrary.
细节CLR内部普遍使用了Load()方法来加载程序集在Load()方法的内部CLR首先会应用这个程序集的版本绑定重定向策略接着在GAC中查找目标程序集。如果GAC中没有找到则会在应用程序目录和子目录中寻找应用配置文件的codebase所指定的位置如果希望加载弱命名程序集Load()方法就不会去GAC中查找当Load()找到目标程序集时就会加载它并返回一个相应Assembly对象的引用 当没有找到程序集时会抛出System.IO.FileNotFoundException异常。 当存在特定CPU架构的程序集时CLR会优先加载当前架构的程序集(例如x86版本优先于IL中立版本) 如果希望强迫加载某个架构版本的程序集需要在强名称中加以指定。ProcessorArchitecture可以为x86 IA64 AMD64或MSIL当然还有None Load方法与Win32函数中的LoadLibrary方法等价 Assembly.LoadFrom() LoadFrom()方法可以从指定文件中加载程序集通过查找程序集的AssemblyRef元数据表得知所有引用和需要的程序集然后在内部调用Load()方法进行加载。例如Assembly.LoadFrom(C:\ABC\Test.dll);
细节 LoadFrom()首先会打开程序集文件通过GetAssemblyName方法得到程序集名称然后关闭文件最后将得到的AssemblyName对象传入Load()方法中 随后Load()方法会再次打开这个文件进行加载。所以LoadFrom()加载一个程序集时会多次打开文件造成了效率低下的现象与Load相比由于内部调用了Load()所以LoadFrom()方法还是会应用版本绑定重定向策略也会在GAC和各个指定位置中进行查找LoadFrom()会直接返回Load()的结果——一个Assembly对象的引用如果目标程序集已经加载过LoadFrom()不会重新进行加载LoadFrom支持从一个URL加载程序集(如http://www.abc.com/test.dll)这个程序集会被下载到用户缓存文件夹中从URL加载程序集时如果计算机未联网LoadFrom会抛出一个异常。如果IE被设置为“脱机工作”则不会抛出异常转而从缓存中寻找已下载的文件Assembly.LoadFile() LoadFile()从一个指定文件中加载程序集它和LoadFrom()的不同之处在于LoadFile()不会加载目标程序集所引用和依赖的其他程序集。您需要自己控制并显示加载所有依赖的程序集 LoadFile()不会解析任何依赖 LoadFile()可以多次加载同一程序集 显式加载依赖程序集的方法是注册AppDomain的AssemblyResolve事件 一些关于C#反射的知识估计也就最多达到使用API的程度至于要深入了解以现在的水平估计很难做到所以下面此篇文章以作为一个阶段的总结。
对于反射的总结我想从以下几个方面展开首先是反射程序集模块类的成员以及成员的一些信息接下来就是动态调用类的成员方法第三个方面就动态产生程序集模块和类以及类的成员。好了现在就让我们从反射各种信息开始吧
在C#中我们要使用反射首先要搞清楚以下命名空间中几个类的关系:
System.Reflection命名空间
(1) AppDomain:应用程序域可以将其理解为一组程序集的逻辑容器
(2) Assembly:程序集类
(3) Module:模块类
(4) Type:使用反射得到类型信息的最核心的类
他们之间是一种从属关系也就是说一个AppDomain可以包含N个Assembly,一个Assembly可以包含N个Module,而一个Module可以包含N个Type.
AppDomain这个类我们等下再来讲解。我们先关注Assembly个类
在程序中如果我们要动态加载一个程序集怎么办呢有几种方式可以使用分别是Load、LoadFrom和LoadWithPartialName三个Assembly的静态方法.
先来讲解Assembly.Load方法该方法会有多个重载版本其中一个就是提供程序集的详细信息即程序集的标识包括程序集的名称版本区域信息公有密钥标记,全部都是以一个字符串的形式提供例如:MyAssembly,Version1.0.0.0,culturezh-CN,PublicKeyToken47887f89771bc57f”.
那么,使用Assembly.Load加载程序集的顺序是怎样的呢首先它会去全局程序集缓存查找然后到应用程序的根目录查找最后会到应用程序的私有路径查找。
当然如果你使用的是弱命名程序集也即只给出程序集的名称那么这个时候CLR将不会在程序集上应用任何安全或者部署策略而且Load也不会到全局缓存程序集中查找程序集。
测试加载弱命名程序集的例子如下:
(1) 新建一个控制台应用程序的工程同时勾选创建解决方案
(2) 在解决方案中新建一个类库的项目随便写一个类和一个方法
(3) 在控制台项目中首先不添加引用直接在Main方法中添加如下代码:
Assembly assembly Assembly.Load(MyAssembly);
if (assembly ! null)
{ Console.WriteLine(加载成功); }
执行程序会抛出异常说找不到该程序集。什么原因呢因为我们使用的是弱命名程序集Load方法不会去全局程序集缓存中查找而该应用程序目录下又没有该程序集所以程序找不到。这个时候我们把程序稍微改一下不用添加代码只需添加对MyAssembly的引用重新运行程序加载成功了。
接下来我们就要看看Load怎么加载强命名程序集了这个步骤稍微有些复杂。还是刚才的项目找到MyAssembly.dll程序集所在的目录一般在binDebug目录下
(1)生成密钥对文件 sn –k MyAssemblyKey.keys
你也可以自己随便起一个密钥对文件名
(2)生成公钥文件
sn –p MyAssemblyKey.keys MyAssemblyPublicKey.PublicKey
注查看公钥命令:sn –tp MyAssemblyPublicKey.PublicKey
(3)创建强命名程序集。
很简单只需要在声明命名空间的那句代码上加上如下特性:
[assembly:AssemblyKeyFileAttribute(”D:TestMyAssemblyKey.keys”)]
(4) 编译项目
(5) 将程序集添加到程序集全局缓存
gacutil –i MyAssembly.dll
这个时候转到加载程序集的项目中将Load方法中的参数改为”程序集名,Version版本,culture区域信息,PublicKeyToken公钥“然后再去掉对程序集的引用我们会发现程序运行成功。表明Load到全局缓存区查找到了该程序集。
使用Load方法加载程序集特别是强命名程序集能在程序集上应用安全和部署策略推荐使用该方法动态加载程序集至于LoadFrom和LoadWithPartialName。
首先我们还是来看看LoadFrom方法这个方法的原理是这样的我们如果要使用它来动态加载程序集必须告诉它程序集的路径也即在哪个目录下面CLR会去加载与你指定的路径完全匹配的程序集。记住当我们指定程序集路径时不能包括任何关于程序集强命名的信息所以CLR不会在我们指定的程序集文件上应用任何策略而且也不会去任何其他的地方搜索程序集简言之它就是指哪打哪呵呵。
例如:你有个程序集在D:/Test/MyAssembly.dll,你要用Assembly.LoadFrom加载该程序集代码就如下:
Assembly assembly Assembly.LoadFrom(”D:/Test/MyAssembly.dll”);
对于,LoadWithParitalName方法推荐大家最好不要使用它因为程序无法确定最终要去加载哪个程序集的版本所以我们这里只是简单的介绍一下它的工作原理你可以传递一个程序集标识给它包括程序集名称至于其他信息是可选的区域信息公有密钥等该方法执行时会首先检查应用程序中配置文件的qualifyAssembly节点如果存在则把该部分名称的程序集替换成完全的程序集标识如果不存在则使用程序集名称先到应用程序根目录下查找然后是私有目录没有找到的话就到程序集全局缓存中查找。简单过程如下: 应用程序根目录 - 应用程序私有目录 - 程序集全局缓存. Assembly.Load()方法Assembly.LoadFrom()方法Assembly.LoadFile()方法的区别 1Assembly.Load()
这个方法通过程序集的长名称包括程序集名版本信息语言文化公钥标记来加载程序集的会加载此程序集引用的其他程序集一般情况下都应该优先使用 这个方法他的执行效率比LoadFrom要高很多而且不会造成重复加载的问题原因在第2点上说明
使用这个方法的时候 CLR会应用一定的策略来查找程序集实际上CLR按如下的顺序来定位程序集
⑴如果程序集有强名称在首先在全局程序集缓(GAC)中查找程序集。
⑵如果程序集的强名称没有正确指定或GAC中找不到那么通过配置文件中的codebase元素指定的URL来查找
⑶如果没有指定强名称或是在GAC中找不到CLR会探测特定的文件夹
假设你的应用程序目录是C:\AppDir,probing元素中的privatePath指定了一个路径Path1,你要定位的程序集是AssemblyName.dll则CLR将按照如下顺序定位程序集 C:\AppDir\AssemblyName.dll C:\AppDir\AssemblyName\AssemblyName.dll C:\AppDir\Path1\AssemblyName.dll C:\AppDir\Path1\AssemblyName\AssemblyName.dll
如果以上方法不能找到程序集会发生编译错误如果是动态加载程序集会在运行时抛出异常
2Assembly.LoadFrom()
这个方法从指定的路径来加载程序集实际上这个方法被调用的时候CLR会打开这个文件获取其中的程序集版本语言文化公钥标记等信息把他们传递给 Load方法接着Load方法采用上面的策略来查找程序集。如果找到了程序集会和LoadFrom方法中指定的路径做比较如果路径相同该程序集会被认为是应用程序的一部分如果路径不同或Load方法没有找到程序集那该程序集只是被作为一个“数据文件”来加载不会被认为是应用程序的一部分。 这就是在第1点中提到的Load方法比LoadFrom方法的执行效率高的原因。另外由于可能把程序集作为“数据文件”来加载所以使用 LoadFrom从不同路径加载相同程序集的时候会导致重复加载。当然这个方法会加载此程序集引用的其他程序集。
3Assembly.LoadFile()
这个方法是从指定的文件来加载程序集和上面方法的不同之处是这个方法不会加载此程序集引用的其他程序集
结论一般大家应该优先选择Load方法来加载程序集如果遇到需要使用LoadFrom方法的时候最好改变设计而用Load方法来代替
另Assembly.LoadFile 与 Assembly.LoadFrom的区别
1、Assembly.LoadFile只载入相应的dll文件比如Assembly.LoadFile(abc.dll)则载入abc.dll假如abc.dll中引用了def.dll的话def.dll并不会被载入。
Assembly.LoadFrom则不一样它会载入dll文件及其引用的其他dll比如上面的例子def.dll也会被载入。
2、用Assembly.LoadFrom载入一个Assembly时会先检查前面是否已经载入过相同名字的Assembly比如abc.dll有两个版本(版本1在目录1下版本2放在目录2下)程序一开始时载入了版本1当使用Assembly.LoadFrom(2\\abc.dll)载入版本2时不能载入而是返回版本1。Assembly.LoadFile的话则不会做这样的检查比如上面的例子换成Assembly.LoadFile的话则能正确载入版本2。
LoadFile:加载指定路径上的程序集文件的内容。LoadFrom: 根据程序集的文件名加载程序集文件的内容。
区别
LoadFile 方法用来来加载和检查具有相同标识但位于不同路径中的程序集.但不会加载程序的依赖项。
LoadFrom 不能用于加载标识相同但路径不同的程序集。