.NET Core 3.0 可回收程序集加载上下文的实现

一、前世今生

.NET诞生以来,程序集的动态加载和卸载都是一个Hack的技术,之前的NetFx都是使用AppDomain的方式去加载程序集,然而AppDomain并没有提供直接卸载一个程序集的API,而是要卸载整个AppDomain才能卸载包含在其中的所有程序集。然而卸载整个CurrentAppDomain会使程序不能工作。可能有人另辟西经,创建别一个AppDomain来加载/卸载程序集,但是由于程序集之间是不能跨域访问的,也导致只能通过Remote Proxy的方式去访问,这样在类型创建和使用上带来了一定的难度也是类型的继承变得相当复杂。

.NET Core中一直没有AppDomain的支持。但是在.NET Core 3.0中,我最期待的一个特性就是对可收集程序集的支持(Collectible AssemblyLoadContext)。 众所周知.NET Core中一直使用AssemblyLoadContext的API,来进行程序集的动态加载,但是并没有提供Unload的方法,此次升级更新了这方面的能力。

二、AssemblyLoadContext

其实这次AssemblyLoadContext的设计,我认为更像是Java中ClassLoader的翻版,可以说非常类似。在使用过程中自定义AssemblyLoadContext可以内部管理其中的程序集,并对整体Context进行Unload。使用AssemblyLoadContext也可以避免程序集名称和版本的冲突。

三、Getting Started

.NET Core 3.0还没有正式版,所有要使用预览版的SDK完成以下实例。我使用的是.NET Core SDK 3.0.100-preview-009812

dotnet new globaljson --sdk-version 3.0.100-preview-009812

AssemblyLoadContext是一个抽象类的,我们需要子类化。下面显示的是我们创建自定义AssemblyLoadContext的方法,实现一个可回收的Context需要在构造器中指定isCollectible: true :

public class CollectibleAssemblyLoadContext : AssemblyLoadContext
{
  public CollectibleAssemblyLoadContext() : base(isCollectible: true)
  { }

  protected override Assembly Load(AssemblyName assemblyName)
  {
    return null;
  }
}

使用netstandard2.0创建一个library

using System;

namespace SampleLibrary
{
  public class SayHello
  {
    public void Hello(int iteration)
    {
      Console.WriteLine($"Hello {iteration}!");
    }
  }
}

测试Load/Unload

var context = new CollectibleAssemblyLoadContext();
var assemblyPath = Path.Combine(Directory.GetCurrentDirectory(),"SampleLibrary.dll");
using (var fs = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read))
{
  var assembly = context.LoadFromStream(fs);

  var type = assembly.GetType("SampleLibrary.SayHello");
  var greetMethod = type.GetMethod("Hello");

  var instance = Activator.CreateInstance(type);
  greetMethod.Invoke(instance, new object[] { i });
}

context.Unload();

GC.Collect();
GC.WaitForPendingFinalizers();

当执行GC收回后,加载的程序集会被完全的回收。

四、最后

GitHub:https://github.com/maxzhang1985/YOYOFx 如果觉还可以请Star下, 欢迎一起交流。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解.NET Core 3.0中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web.桌面.机器学习.容器.IoT 等的版本 3.0. .NET Core 1 .NET Core 的历史可追溯到几年前,版本 1 是在 2016 年推出,旨在生成第一版开放源代码和跨平台(Windows.macOS 和 Linux)的 .NET.灵感来源于只能使用开放源代码框架的客户,以及需要在 Li

  • ASP.NET Core新建项目教程(3)

    ASP.NET Core - 新建项目 在这一章,我们将讨论如何在Visual Studio中创建一个新项目. 只要你安装了Visual Studio 2015的.net core工具,您就可以开始构建一个新的ASP.net core应用程序,从菜单选择:File → New Project 在新项目对话框中,您将看到以下三个不同的Web项目模板 ASP.NET Web Application−简单的ASP.NET应用程序的模板. ASP.NET Core Web Application (.N

  • asp.net Core3.0区域与路由配置的方法

    在ASP.NET Core 3.0中路由配置和2.0不一样了 一.MVC 服务注册 ASP.NET Core 3.0 添加了用于注册内部的 MVC 方案的新选项Startup.ConfigureServices. 三个新的顶级扩展方法与 MVC 方案上IServiceCollection可用. 模板使用这些新方法,而不是UseMvc. 但是,AddMvc继续像它已在以前的版本. 下面的示例将添加对控制器和与 API 相关的功能,但不是视图或页面的支持. API 模板使用此代码: public v

  • 使用.NET Core3.0创建一个Windows服务的方法

    在.NET Core 3.0 中,我们引入了一种名为 Worker Service 的新型应用程序模板.此模板旨在为您在 .NET Core 中编写长时间运行的服务的提供一个起点.在本演练中,我们将创建一个 worker 并将其作为 Windows 服务运行. 创建一个 Worker 注意:在我们的预览版中,worker 模板与 Web 模板位于同一级菜单中.这将在未来的版本中发生变化.我们打算将 Worker Service 模板直接放在"创建新项目"菜单中. 在 Visual St

  • .NET Core 3.0之创建基于Consul的Configuration扩展组件

    经过前面三篇关于.NET Core Configuration的文章之后,本篇文章主要讨论如何扩展一个Configuration组件出来. 了解了Configuration的源码后,再去扩展一个组件就会比较简单,接下来我们将在.NET Core 3.0-preview5的基础上创建一个基于Consul的配置组件. 相信大家对Consul已经比较了解了,很多项目都会使用Consul作为配置中心,此处也不做其他阐述了,主要是讲一下,创建Consul配置扩展的一些思路.使用Consul配置功能时,我们

  • 浅谈从ASP.NET Core2.2到3.0你可能会遇到这些问题

    趁着假期的时间所以想重新学习下微软的官方文档来巩固下基础知识.我们都知道微软目前已经发布了.NET Core3.0的第三个预览版,同时我家里的电脑也安装了vs2019.So,就用vs2019+.NET Core3.0来跟着做一下Contoso University这个WEB应用,但是在基于3.0进行操作的时候遇到了一些问题,所以我就查看了微软的<从 ASP.NET Core 迁移 2.2 到 3.0 预览版 2>这篇文档,就着今天遇到的问题,所以我整理下,希望对大伙有所帮助,当然大伙也可以直接

  • .NET Core 3.0 可回收程序集加载上下文的实现

    一.前世今生 .NET诞生以来,程序集的动态加载和卸载都是一个Hack的技术,之前的NetFx都是使用AppDomain的方式去加载程序集,然而AppDomain并没有提供直接卸载一个程序集的API,而是要卸载整个AppDomain才能卸载包含在其中的所有程序集.然而卸载整个CurrentAppDomain会使程序不能工作.可能有人另辟西经,创建别一个AppDomain来加载/卸载程序集,但是由于程序集之间是不能跨域访问的,也导致只能通过Remote Proxy的方式去访问,这样在类型创建和使用

  • Android 3.0引入的异步加载机制Loader

    Loader是谷歌在Android 3.0引入的异步加载机制,能够对数据异步加载并显示到Activity或Fragment上,使用者不需要对数据的生命周期进行管理,而是交给Loader机制来管理. 使用Loader的优点 假如我们需要从网络上获取数据,通常的做法是使用子线程Thread+Handler或者是使用AsyncTask来处理. Thread+Handler方法实现起来简单直观,不过会麻烦点,需要自己实现Handler子类,创建线程,还要管理Handler的生命周期. AsyncTask

  • ASP.NET Core中修改配置文件后自动加载新配置的方法详解

    前言 在 ASP.NET Core 默认的应用程序模板中, 配置文件的处理如下面的代码所示: config.AddJsonFile( path: "appsettings.json", optional: true, reloadOnChange: true ); config.AddJsonFile( path: $"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: t

  • Scratch3.0 页面初始化同时加载sb3文件的操作代码

    scratch是一种非常合适的培养自己的编程兴趣的方式.通过拖拽的方式,可以实现一些游戏,小程序的开发,就像搭积木一样,下面给大家介绍Scratch3.0 页面初始化同时加载sb3文件的操作方法,一起看看吧! 目标文件地址:src\containers\sb-file-uploader.jsx 修改 sb-file-uploader.jsx文件, class SBFileUploader中添加componentDidMount(),代码如下 componentDidMount() { var _

  • C# 动态加载程序集信息

    在设计模式的策略模式中,需要动态加载程序集信息,本文通过一个简单的实例,来讲解动态加载Dll需要的知识点. 涉及知识点: AssemblyName类,完整描述程序集的唯一标识, 用来表述一个程序集. Assembly类,在System.Reflection命名空间下,表示一个程序集,它是一个可重用.无版本冲突并且可自我描述的公共语言运行时应用程序构建基块. Module类 表述在模块上执行反射,表述一个程序集的模块信息. Type类,在System命名空间下,表示类型声明:类类型.接口类型.数组

  • .net加载失败的程序集实现重新加载

    在.net程序中,程序集是Lazy加载的,只有在用的时候才会去加载,当程序集加载失败时,会触发AppDomain.AssemblyResolve的事件,在这个事件中,我们甚至还可以进行补救,从别得地方重新加载程序集. AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { byte[] content = getLibBytes(e.Name); return Assembly.Load(content); }; 这个功能如果使用起来就非常灵

  • asp.net 未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。

    说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详细信息: System.BadImageFormatException: 未能加载文件或程序集"XXX"或它的某一个依赖项.试图加载格式不正确的程序. 源错误: 执行当前 Web 请求期间生成了未处理的异常.可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息. 程序集加载跟踪: 下列信息有助于确定程序集"XXX"无法加载的

  • LazyLoad 延迟加载(按需加载)

    1:实际需求 大型网站往往很矛盾,想用户在首页看到更多东西,又不想浪费太多服务器流量.比如一个有3屏的首页.可能50%的用户进首页的目的是点击首页的连接,到子页面. 那么我们的网站却为100%的用户加载了 3个 屏幕的所有内容.如果可以按需加载内容.就可以节约更多资源,做更多好的应用. 2:解决方案 用客户端语言来判断用户当前的可视范围,只加载用户可视范围的内容.最主要的是图片.因为文字信息,相对较小,其他多媒体内容相对占用服务器流量更多. 3:演示例子(最后提供)4:解析 首先我们要分析下,这

  • Android实现加载广告图片和倒计时的开屏布局

    这是一个android开屏布局的实例,可以用于加载广告图片和倒计时的布局.程序中设置的LayoutParams,划分额外空间比例为6分之5,具体权重比例可根据用户自己需求来自定义,异步加载广告图片,相关的Android代码. 具体实现代码如下: package cn.waps.extend; import android.app.Activity; import android.content.Context; import android.content.res.Configuration;

  • iOS 图片加载框架SDWebImage解读

    目的 在使用SDWebImage加载图片时,尤其是加载gif等大图时,SDWebImage会将图片缓存在内存中,这样是非常吃内存的,这时我们就需要在适当的时候去释放一下SDWebImage的内存缓存,才不至于造成APP闪退. SDWebImage提供了 UIImageView.UIButton .MKAnnotationView 的图片下载分类,只要一行代码就可以实现图片异步下载和缓存功能. 这样开发者就无须花太多精力在图片下载细节上,专心处理业务逻辑. SDWebImage 特点 提供 UII

随机推荐