本文主要介绍C#汇编的详细讲解。负载情况。本文通过一个简单的案例来说明对这项技术的理解和使用。以下是详细内容。有需要的朋友可以参考一下。
当我们使用汇编时。在C#语言中加载加载托管程序集,使用反射函数,我们一般需要通过assembly.load()、assembly.loadfrom()等方法将目标托管程序集加载到当前应用域中,然后生成相应的实例,最后调用实例的属性或方法。
一般来说,我们可以像汇编一样调用方法。加载没有问题,但是装配。Load方法不能处理下列情况:
该程序集可能被延迟签名。
该程序集可能受CAS策略保护。
宿主程序和目标程序集具有不同的处理器体系结构。
加载目标程序集时,目标程序集中的方法可能正在运行。(例如,模块初始化)
绑定策略可能会应用到程序集,您可能得不到想要的程序集。
现在我们重点关注第四种情况,因为这种情况是最常见的。我们思考以下问题:
1. 为什么目标程序集的方法在运行时不允许再加载一次?
准确地说,为什么默认情况下,一个应用程序域中加载的程序集不允许在另一个应用程序域中加载?这是因为首次加载应用程序集时,程序集。Load方法将锁定程序集,以防止应用程序集在自己使用期间被其他应用程序修改(通常称为删除)。实际上,这与Win32 API中的CreateFile函数类似。众所周知,Windows中占用文件最直接最简单的方法就是调用CreateFile API函数打开文件。请参考:
https://www.jb51.net/article/221122.htm
2. Assembly.Load 方法能否实现在加载目标程序集时不锁定它?
我们可以用下面的代码加载我们的程序集:
byte[] buffer=System。IO . file . read all bytes(yourfull filename path);
//使用字节数组加载程序集
装配装配=装配。负载(缓冲);
后台实现是临时锁定目标程序集,然后将程序集的内容复制到内存中,读取后解锁程序集并从内存中加载目标程序集的副本。
如果您需要通过上述方法在GAC中加载程序集,您可以通过以下代码来完成:
string assembly name=' assembly test,Version=1.0.0.0,Culture=neutral,public key token=fffb 45 e 56 DD 478 e 3 ';
ass=Assembly。ReflectionOnlyLoad(assembly name);
byte[] buffer=System。IO.File.ReadAllBytes(ass。位置);
装配装配=装配。负载(缓冲);
3. Assembly.Load 方法的缓存
当我们使用组件时。Load series方法加载目标程序集,可能会出现各种导致加载失败的情况,最常见的是目标程序集不存在导致加载失败。失败后,我们可能想再加载一次,或者多次加载,直到成功,但之后默认无法实现。NET框架2.0。原因是之后。NET Framework 2.0,程序集。Load方法有一个缓存,目标程序集第一次加载的失败或成功状态都会被缓存,这样下次加载目标程序集时就不会真正加载了,目标程序集的内容和状态直接从缓存中取出。
在这种情况下,我们可以将以下配置信息添加到调用程序集的宿主程序的app.config中。禁用缓存的加载方法:
?xml版本='1.0 '?
配置
运行时间
disableCachingBindingFailures enabled=' 1 '/
/运行时
启动
supportedRuntime版本='v2.0.50727'/
/启动
/配置
4. 还有其他方案吗?
CLR框架草图:
目前,程序集的加载和卸载完全由应用程序域控制,一个程序集只能通过应用程序域加载和卸载,其他方式都不行!
然后我们可以在需要的时候将目标程序集加载到应用程序域中,不需要的时候卸载应用程序域,但是当前的应用程序域只能通过关闭程序来卸载。
到目前为止,看似无解了,但是我们忽略了一个事实,那就是我们可以在当前应用程序域中创建子应用程序域。可以通过在子应用程序域中进行程序集的加载,或者说只要涉及程序集加载的全部放在子应用程序域中,主应用程序域中不做任何与程序集加载有关的事情。
这部分内容我就不详细介绍了,大家可以参考:
http://www。代码项目。将单独目录中的程序集加载到
5. 我们确实需要使用Assembly.Load吗?
因为组装。负荷是将整个程序集以及其相关的依赖程序集全部加载进来,只要有一个出错就会导致加载失败。如果我们只是为了使用当前程序集的类型,而不是使用其方法或者属性的话就完全可以抛弃组装。负荷方法。
微软在100 .净框架2.0时介绍了几个新的程序集加载API:
组装ReflectionOnlyLoadFrom(字符串程序集文件)
组装ReflectionOnlyLoad(byte[]原始程序集)
组装ReflectionOnlyLoad(字符串程序集名称)
基于开篇提到的组装。负荷方法的5种问题,仅反射程序集加载蜜蜂可以:
跳过程序集强命名认证。
跳过程序集国际体育仲裁法庭策略认证。
跳过处理器架构检查规则。
不在目标程序中执行任何方法,包括构造函数。
不应用任何绑定策略。
使用时有如下几个注意事项:
1) CLR不会搜索目标程序集所依赖的程序集,我们必须通过ReflectionOnlyAssemblyResolve(程序集。负荷中的对应事件是AssemblyResolve)事件手动处理。
2) 不可以在通过仅反射方法加载进来的程序集执行任何方法,包括构造函数,只可以获取程序集的信息和类型。
3) 建议使用组装ReflectionOnlyLoadFrom方法,但是如果目标程序集在(同粒状活性炭)颗粒状活性炭中那么可以使用组装ReflectionOnlyLoad方法。
具体示例代码如下:
使用系统;
使用系统。木卫一;
使用系统。反思;
公共类ReflectionOnlyLoadTest
{
私有字符串m _ rootAssembly
public ReflectionOnlyLoadTest(字符串根程序集)
{
m _ rootAssembly=rootAssembly
}
公共静态void Main(String[] args)
{
if (args .长度!=1)
{
控制台WriteLine(“用法:测试装配路径”);
返回;
}
尝试
{
ReflectionOnlyLoadTest rolt=new ReflectionOnlyLoadTest(args[0]);
罗尔特run();
}
捕捉(例外e)
{
控制台WriteLine('异常:{0}!'e .消息);
}
}
内部无效运行()
{
AppDomain curDomain=AppDomain .当前域
凝胶域ReflectionOnlyAssemblyResolve=
新建resolve eventhandler(MyReflectionOnlyResolveEventHandler);
装配组件=程序集ReflectionOnlyLoadFrom(m _ root assembly);
//strong制加载所有依赖项
Type[] types=asm .GetTypes();
//显示当前appdomain中的仅反射程序集
控制台WriteLine(' -检查上下文-');
foreach(凝乳域中的程序集答.ReflectionOnlyGetAssemblies())
{
控制台WriteLine(“程序集位置:{0}”,a .位置);
控制台WriteLine('程序集名称:{0} ',a .全名);
控制台WriteLine();
}
}
私有程序集MyReflectionOnlyResolveEventHandler(对象发送方,ResolveEventArgs参数)
{
程序集名称name=新程序集名称(参数.姓名);
String asmToCheck=Path .get directory name(m _ root assembly)" \ "名称。姓名. dll ';
如果(文件。存在(asmToCheck))
{
返回装配ReflectionOnlyLoadFrom(asmToCheck);
}
返回装配ReflectionOnlyLoad(参数。姓名);
}
}
6. 为什么没有Assembly.UnLoad 方法?
以下是清除(清除的缩写)产品单元经理(部门经理)杰森詹德文章中的内容的整理:
1)为了确保CLR中代码引用的代码地址有效,必须跟踪GC对象和COM CCW等特殊应用程序。否则,卸载程序集后,将会有CLR对象或COM组件使用该程序集的代码或数据地址,这将导致访问异常。为了避免这种错误追踪,目前是在AppDomain级别进行的。如果你想加入支持大会。卸载,追踪的粒度必须降低到汇编的级别,这在技术上不是不可以,只是成本太高。2) If组装。支持卸载,必须跟踪每个汇编代码使用的句柄和对现有托管代码的引用。比如JITer编译方法的时候,生成的代码都在一个统一的区域。如果要支持卸载程序集,必须单独编译每个程序集。此外,还有一些类似的资源使用问题。虽然分离跟踪在技术上是可行的,但成本会很高,尤其是在WinCE等资源有限的系统中。CLR支持跨AppDomain程序集加载优化,即域中立的优化,使得多个AppDomain共享一个代码,加快加载速度。目前v1.0和v1.1还不能处理卸载域中性类型代码。这也使得汇编的完整语义难以实现。倾销
详情请参考https://www.jb51.net/article/221129.htm。
http://blogs.msdn.com/b/jasonz/archive/2004/05/31/145105.aspx
7. 需要牢记的经验
1)只加载需要直接调用的程序集,不加载目标程序集内部引用的程序集和其他不相关的程序集。
2)可以使用RefelectionLoad方法加载的程序集不应使用该程序集加载。加载方法。
3)一旦出现加载错误,不要明明以为程序集不存在!检查程序集加载缓存,同一个程序集是否由不同的应用程序域加载等。
到目前为止,我们已经解释了程序集的一些特性。加载方法。你知道了吗?
参考链接:
http://msdn . Microsoft . com/en-us/library/t07a 3 dye(v=vs . 71)。aspx
http://blogs . msdn . com/b/jun feng/archive/2004/11/03/252033 . aspx
http://blogs . msdn . com/b/jun feng/archive/2004/08/24/219691 . aspx
http://www.sosuo8.com/article/show.asp?id=2979
http://msdn.microsoft.com/en-us/library/ms404279.aspx
http://blog.csdn.net/xt_xiaotian/article/details/6362450
http://blogs.msdn.com/b/jasonz/archive/2004/05/31/145105.aspx
http://www.cnblogs.com/ccBoy/archive/2004/07/13/23636.html
http://www.cnblogs.com/wayfarer/archive/2004/09/29/47896.html
http://www . code project . com/Articles/42312/Loading-Assemblies-in-Separate-directory-Into-a
http://msdn.microsoft.com/en-us/library/ms404312.aspx
本文关于C#汇编的详细讲解到此为止。负载情况。有关C#程序集的更多信息。加载,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。