.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下, 欢迎一起交流。
.NET Core 开源学习群:214741894
.NET Core 3.0 可回收程序集加载上下文的更多相关文章
- .NET 的程序集加载上下文
原文:.NET 的程序集加载上下文 我们编写的 .NET 应用程序会使用到各种各样的依赖库.我们都知道 CLR 会在一些路径下帮助我们程序找到依赖,但如果我们需要手动控制程序集加载路径的话,需要了解程 ...
- .NET Core 3.0 可卸载程序集原理简析
因为最近在群里被问到如何理解 .NET Core 3.0 可卸载程序集,所以就写了这篇简单的分析. 因为时间实在很少,这篇文章只简单的罗列了相关的代码,请配合官方说明文档理解. 另外,书籍<.N ...
- 重温CLR(十七)程序集加载和反射
本章主要讨论在编译时对一个类型一无所知的情况下,如何在运行时发现类型的信息.创建类型的实例以及访问类型的成员.可利用本章讲述的内容创建动态可扩展应用程序. 反射使用的典型场景一般是由一家公司创建宿主应 ...
- clr via c# 程序集加载和反射(2)
查看,clr via c# 程序集加载和反射(1) 8,发现类型的成员: 字段,构造器,方法,属性,事件,嵌套类型都可以作为类型成员.其包含在抽象类MemberInfo中,封装了所有类型都有的一组属性 ...
- clr via c# 程序集加载和反射集(一)
1,程序集加载---弱的程序集可以加载强签名的程序集,但是不可相反.否则引用会报错!(但是,反射是没问题的) //获取当前类的Assembly Assembly.GetEntryAssembly() ...
- CLR中的程序集加载
CLR中的程序集加载 本次来讨论一下基于.net平台的CLR中的程序集加载的机制: [注:由于.net已经开源,可利用vs2015查看c#源码的具体实现] 在运行时,JIT编译器利用程序集的TypeR ...
- [Asp.net mvc]实体更新异常:存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。
学习asp.net mvc 时在更新实体进行SaveChanges()的时候出现了异常,异常如下: “/”应用程序中的服务器错误. 存储区更新.插入或删除语句影响到了意外的行数(0).实体在加载后可能 ...
- 【C#进阶系列】23 程序集加载和反射
程序集加载 程序集加载,CLR使用System.Reflection.Assembly.Load静态方法,当然这个方法我们自己也可以显式调用. 还有一个Assembly.LoadFrom方法加载指定路 ...
- 存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。刷新 ObjectStateManager 项。
在用asp.net MVC3 的MusicStore时候 Edit某个数据项时提示下面的错误: 存储区更新.插入或删除语句影响到了意外的行数(0).实体在加载后可能被修改或删除.刷新 ObjectSt ...
随机推荐
- Mysql: 强制走索引:mysql between 日期索引 索引问题-日期索引使用
Mysql: mysql between 日期索引 索引问题-日期索引使用 表结构: dep_date dep arr 联合索引: ind_coll_date_route (dep_date ,de ...
- 高并发下用pdo,文件排它锁,redis三种方法对比
<?php header('content-type:text/html;charset=utf-8'); // //无控制 // $DB_DSN = ' ...
- 有關WCF一個自認爲比較經典的博客
无废话WCF入门教程四[WCF的配置文件] (http://www.cnblogs.com/iamlilinfeng/archive/2012/10/02/2710224.html) -------- ...
- pom详解
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- Mysql异常_01_ 誓死登进mysql_Can't connect to MySQL server on 'localhost' (10061)
现象:打开cmd,输入命令:mysql -uroot -p 回车之后,输入密码,结果进不去mysql,并且抛出异常 异常:Can't connect to MySQL server on 'local ...
- Android: 利用SurfaceView绘制股票滑动直线解决延迟问题
1.背景介绍 最近项目要绘制股票走势图,并绘制能够跟随手指滑动的指示线(Indicator)来精确查看股票价格和日期.如下图所示: 上图中的那条白色直线就是股票的指示线,用来跟随手指精确确定股票的时间 ...
- 【C/C++】scanf,printf 函数
摘自http://www.cplusplus.com 1. scanf 函数 int scanf ( const char * format, ... ); Parameters format C s ...
- photonView 空指针异常
1.OBJ上要有PhotonView 脚本 2.PhotonNetwork.Instantiate方法初始化出来OBJ OBJ 预制体要放在Resources文件夹下 PhotonNetwork.In ...
- docker异常处理
Error running DeleteDevice dm_task_run failed重启docker即可 Error starting daemon: error initializing gr ...
- JavaScript下的进制转换
JavaScript下的进制转换 //十进制转其他进制 var num = 99; console.log('十进制: ', num); console.log('八进制:', (num).toStr ...