• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

C# Assembly.Load案例详解

c# 搞代码 4年前 (2022-01-09) 23次浏览 已收录 0个评论

 我们在使用C# 语言的Assembly.Load 来加载托管程序集并使用反射功能时,一般需要先通过Assembly.Load(), Assembly.LoadFrom() 等方法将目标托管程序集加载到当前应用程序域中,然后生成对应实例,最后再进行调用实例的属性或者方法。

一般情况下,我们调用Assembly.Load 一类方法是不会出问题的,但是对于以下几种情况Assembly.Load 方法无法处理:

  1. 程序集可能是延迟签名的。
  2. 程序集可能被CAS 策略保护。
  3. 宿主程序与目标程序集的处理器架构不同。
  4. 当加载目标程序集时,目标程序集中的方法可能正在运行。 (比如,模块初始化)
  5. 程序集可能应用了绑定策略, 你可能不会得到你想要的那个程序集。

我们现在关注第四种情况,因为这种情况是最常见的。我们思考以下几个问题:

1. 为什么目标程序集的方法在运行时不允许再加载一次?

准确地说是为什么在一个应用程序域(AppDomain)中加载后的程序集默认不允许再另外一个应用程序域中加载?这是因为在第一次加载应用程序集时,Assemlby.Load 方法会将此程序集锁住,以防止在自己使用过程中应用程序集被其他应用程序修改(一般指删除)。这其实与Win32 API 中的CreateFile 函数行为类似,我们都知道,在 Windows 中去占用一个文件最直接、最简单的方式就是调用 CreateFile API 函数来打开文件。具体请参照:

 

2. Assembly.Load 方法能否实现在加载目标程序集时不锁定它?

我们可以使用如下代码加载我们的程序集:

byte[] buffer = System.IO.File.ReadAllBytes(yourFullfileNamePath);

//Load assembly using byte array

Assembly assembly = Assembly.Load(buffer);

后台的实现是暂时先将目标程序集锁定,然后把程序集内容复制到内存中,读取后将程序集解锁并从内存中加载目标程序集的拷贝。

如果你需要通过上面的方法加载GAC 中的程序集,那么可以通过如下代码实现:

string assemblyName = "AssemblyTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=fffb45e56dd478e3";

Assembly ass = Assembly.ReflectionOnlyLoad(assemblyName);

byte[] buffer = System.IO.File.ReadAllBytes(ass.Location);

Assembly assembly = Assembly.Load(buffer);

3. Assembly.Load 方法的缓存

在我们使用Assembly.Load 系列方法加载目标程序集时,可能有各种情况导致加载失败,最常见的是目标程序集不存在而导致加载失败问题。失败后我们可能想要再加载一次或者加载多次直到成功为止,但是在.NET Framework 2.0 以后默认是无法实现的,原因在于.NET Framework 2.0 以后 Assembly.Load 方法有缓存,第一次加载目标程序集的失败或者成功的状态都会被缓存,这样在你下一次加载目标程序集时不会真的加载,会直接从缓存里取目标程序集的内容和状态。

对这种情况我们可以在调用Assembly.Load 方法的宿主程序的app.config 中加入如下配置信息来禁用缓存:

<?xml version="1.0"?>
<configuration>
  <runtime>
    <disableCach<b style="color:transparent">本文来源gao@!dai!ma.com搞$$代^@码!网!</b>ingBindingFailures enabled="1" />
  </runtime>
  <startup>
    <supportedRuntime version="v2.0.50727"/>
  </startup>
</configuration>

4. 还有其他方案吗?

CLR 框架略图:


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:C# Assembly.Load案例详解

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址