,,C# Assembly.Load案例详解

,,C# Assembly.Load案例详解

本文主要介绍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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • 设计一个简单的C#控制台应用程序,C#控制台程序,C# 创建控制台应用程序
  • 深入解析windows第8版,深入解析C#(第4版)
  • 数组代码,c# 数组操作,C# 数组实例介绍(图文)
  • 学会C#要多久,学会c#要多久,c#学习之30分钟学会XAML
  • 回溯法01背包问题c,回溯法求解01背包问题伪代码,C#使用回溯法解决背包问题实例分析
  • xml文件转义字符,xml转意字符,C# XML中的转义字符操作
  • winform 进度条控件,c# 进度条使用
  • winform 进度条控件,c# 进度条使用,C#使用winform实现进度条效果
  • winform backgroundworker,c# isbackground
  • winform backgroundworker,c# isbackground,C# BackgroundWorker用法详解
  • lua与c#交互,lua c#
  • lua与c#交互,lua c#,ToLua框架下C#与Lua代码的互调操作
  • linq c#,linq原理 c#
  • linq c#,linq原理 c#,c#中LINQ的基本用法实例
  • java decimal保留两位小数,sql中decimal函数保留2位小数,C#中decimal保留2位有效小数的实现方法
  • 留言与评论(共有 条评论)
       
    验证码: