一、前世今生

.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下, 欢迎一起交流。

  .NET Core 开源学习群:214741894

.NET Core 3.0 可回收程序集加载上下文的更多相关文章

  1. .NET 的程序集加载上下文

    原文:.NET 的程序集加载上下文 我们编写的 .NET 应用程序会使用到各种各样的依赖库.我们都知道 CLR 会在一些路径下帮助我们程序找到依赖,但如果我们需要手动控制程序集加载路径的话,需要了解程 ...

  2. .NET Core 3.0 可卸载程序集原理简析

    因为最近在群里被问到如何理解 .NET Core 3.0 可卸载程序集,所以就写了这篇简单的分析. 因为时间实在很少,这篇文章只简单的罗列了相关的代码,请配合官方说明文档理解. 另外,书籍<.N ...

  3. 重温CLR(十七)程序集加载和反射

    本章主要讨论在编译时对一个类型一无所知的情况下,如何在运行时发现类型的信息.创建类型的实例以及访问类型的成员.可利用本章讲述的内容创建动态可扩展应用程序. 反射使用的典型场景一般是由一家公司创建宿主应 ...

  4. clr via c# 程序集加载和反射(2)

    查看,clr via c# 程序集加载和反射(1) 8,发现类型的成员: 字段,构造器,方法,属性,事件,嵌套类型都可以作为类型成员.其包含在抽象类MemberInfo中,封装了所有类型都有的一组属性 ...

  5. clr via c# 程序集加载和反射集(一)

    1,程序集加载---弱的程序集可以加载强签名的程序集,但是不可相反.否则引用会报错!(但是,反射是没问题的) //获取当前类的Assembly Assembly.GetEntryAssembly() ...

  6. CLR中的程序集加载

    CLR中的程序集加载 本次来讨论一下基于.net平台的CLR中的程序集加载的机制: [注:由于.net已经开源,可利用vs2015查看c#源码的具体实现] 在运行时,JIT编译器利用程序集的TypeR ...

  7. [Asp.net mvc]实体更新异常:存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。

    学习asp.net mvc 时在更新实体进行SaveChanges()的时候出现了异常,异常如下: “/”应用程序中的服务器错误. 存储区更新.插入或删除语句影响到了意外的行数(0).实体在加载后可能 ...

  8. 【C#进阶系列】23 程序集加载和反射

    程序集加载 程序集加载,CLR使用System.Reflection.Assembly.Load静态方法,当然这个方法我们自己也可以显式调用. 还有一个Assembly.LoadFrom方法加载指定路 ...

  9. 存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。刷新 ObjectStateManager 项。

    在用asp.net MVC3 的MusicStore时候 Edit某个数据项时提示下面的错误: 存储区更新.插入或删除语句影响到了意外的行数(0).实体在加载后可能被修改或删除.刷新 ObjectSt ...

随机推荐

  1. css 动画的例子

    1. [代码]   <!DOCTYPE HTML><html><head><meta charset="utf-8"><tit ...

  2. django 链接地址匹配流程

    前提: 代码结构 步骤一: 下面为某个网页的链接地址 <body> {% if latest_article_list %} <ul> {% for article in la ...

  3. vi 常用编辑命令

    什么是vi: vi是Linux/Unix底下最常用的文本编辑器,可以理解为和Windows下的txt一样,咱们一般操作linux服务器的时候都是没有图形化界面的, 怎么移动光标,到哪个位置,替换修改什 ...

  4. Java微信开发_Exception_03_errcode:48001 errmsg:api unauthorized hint

    创建菜单时出现这个异常, 异常信息:errcode:48001 errmsg:api unauthorized hint 解读:调用的接口没有权限. 回去公众号后台一看,发现真的没有自定义菜单的权限, ...

  5. 【BZOJ 4709】柠檬 斜率优化dp+单调栈

    题意 给$n$个贝壳,可以将贝壳分成若干段,每段选取一个贝壳$s_i$,这一段$s_i$的数目为$num$,可以得到$num^2\times s_i$个柠檬,求最多能得到几个柠檬 可以发现只有在一段中 ...

  6. POJ-1741(树分治)

    树的点分治 给出详细的讲解!!点这里打开论文-分治算法在树的路径问题中的应用 本题目是他讲的第一个例题: 我的理解:每次都找树的重心,计算以重心为根的子树之间所贡献的答案.不断这样下去:如果这棵树是一 ...

  7. django学习笔记(一)视图和url配置

    1.开始一个项目: 进入创建的目录,然后: django-admin startproject myblog 2.启动开发服务器: python manage.py runserver 注:默认是80 ...

  8. python 标准库 —— 线程与同步(threading、multiprocessing)

    1. 创建线程 使用 os 下的 fork() 函数调用(仅限 Unix 系统) import os print('current process (%s) starts ...' % (os.get ...

  9. 【遍历二叉树】07恢复二叉搜索树【Recover Binary Search Tree】

    开一个指针数组,中序遍历这个二叉搜索树,将节点的指针依次保存在数组里, 然后寻找两处逆序的位置, 中序便利里BST得到的是升序序列 ++++++++++++++++++++++++++++++++++ ...

  10. ffmpeg解码RTSP/TCP视频流H.264(QT界面显示视频画面)

    源码下载地址: http://download.csdn.net/detail/liukang325/9489952 我用的ffmpeg版本为 ffmpeg-2.1.8.tar.bz2 版本低了恐怕有 ...