聊一聊 .NET 的 AssemblyLoadContext 可插拔程序集
聊一聊 .NET 的 AssemblyLoadContext 可插拔程序集引言程序集加载的痛点在传统的 .NET Framework 时代应用程序域AppDomain提供了程序集隔离的能力但它的使用较为复杂且性能开销较大。到了 .NET Core/.NET 5微软引入了AssemblyLoadContextALC这是一种轻量级的程序集加载上下文机制。ALC 的核心价值在于允许开发者在同一个进程中加载多个版本的程序集、实现动态卸载、构建插件系统等。本文将深入剖析 ALC 的原理并通过代码示例展示其可插拔能力。## ALC 的核心原理### 什么是 AssemblyLoadContextAssemblyLoadContext是 .NET 中用于管理程序集加载和隔离的抽象类。每个 ALC 实例维护一个独立的程序集缓存、类型解析逻辑和依赖关系图。默认情况下.NET 运行时使用AssemblyLoadContext.Default默认上下文加载核心库和应用程序主程序集。通过自定义 ALC我们可以-隔离依赖不同插件可以使用不同版本的程序集而不会冲突。-动态卸载通过Unload()方法释放不再需要的程序集和类型仅适用于可收集的 ALC。-可插拔加载从非标准路径如网络、加密文件、内存流加载程序集。### 工作原理图解ALC 的加载流程如下1. 程序集请求进入 ALC。2. ALC 检查自身缓存是否已有该程序集。3. 若未命中调用Load或LoadFromAssemblyName方法可重写。4. 解析依赖时递归调用父上下文通常是默认上下文。5. 加载完成后程序集被缓存到该 ALC 中。这种设计使得每个 ALC 可以拥有独立的程序集视图实现“沙箱”效果。## 可插拔场景构建插件系统假设我们需要一个日志插件系统主程序加载不同版本的日志库而插件之间互不干扰。下面通过两个代码示例演示如何实现。### 示例 1基本 ALC 实现——从指定路径加载程序集csharpusing System;using System.Reflection;using System.Runtime.Loader;// 自定义 ALC从插件目录加载程序集public class PluginLoadContext : AssemblyLoadContext{ private readonly string _pluginPath; public PluginLoadContext(string pluginPath) : base(isCollectible: true) // 启用可收集支持卸载 { _pluginPath pluginPath; } // 重写 Load 方法指定程序集加载路径 protected override Assembly Load(AssemblyName assemblyName) { // 检查是否是插件程序集 if (assemblyName.Name MyPlugin) { string assemblyFile System.IO.Path.Combine(_pluginPath, MyPlugin.dll); return LoadFromAssemblyPath(assemblyFile); } // 其他程序集如 System.Runtime回退到默认上下文 return AssemblyLoadContext.Default.LoadFromAssemblyName(assemblyName); }}class Program{ static void Main() { // 创建两个不同的 ALC 实例模拟插件隔离 var context1 new PluginLoadContext(C:\Plugins\Version1); var context2 new PluginLoadContext(C:\Plugins\Version2); // 加载插件假设 MyPlugin 中有 IPlugin 接口实现 var plugin1 context1.LoadFromAssemblyName(new AssemblyName(MyPlugin)); var plugin2 context2.LoadFromAssemblyName(new AssemblyName(MyPlugin)); Console.WriteLine($插件1程序集引用{plugin1.FullName}); Console.WriteLine($插件2程序集引用{plugin2.FullName}); // 验证隔离性两个 ALC 中的 MyPlugin 是不同对象 Console.WriteLine($程序集是否相同{plugin1 plugin2}); // 输出 False }}注释说明-isCollectible: true启用卸载能力但需要确保无外部引用。- 重写Load方法时优先加载插件程序集非插件程序集如 BCL回退到默认上下文避免重复加载。- 通过两个 ALC 实例加载相同名称的程序集它们的内存副本和类型是独立的。### 示例 2动态卸载与释放资源csharpusing System;using System.Reflection;using System.Runtime.Loader;// 可卸载的插件上下文public class UnloadablePluginContext : AssemblyLoadContext{ public UnloadablePluginContext() : base(isCollectible: true) { } protected override Assembly Load(AssemblyName assemblyName) { // 假设插件文件为 Plugin.dll if (assemblyName.Name Plugin) { string pluginDir System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Plugins); string pluginPath System.IO.Path.Combine(pluginDir, Plugin.dll); return LoadFromAssemblyPath(pluginPath); } return AssemblyLoadContext.Default.LoadFromAssemblyName(assemblyName); }}class Program{ static void Main() { WeakReference alcWeakRef; WeakReference assemblyWeakRef; // 创建作用域确保引用被释放 CreateAndLoadPlugin(out alcWeakRef, out assemblyWeakRef); // 强制垃圾回收 GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine($ALC 是否存活{alcWeakRef.IsAlive}); // 输出 False Console.WriteLine($程序集是否存活{assemblyWeakRef.IsAlive}); // 输出 False } static void CreateAndLoadPlugin(out WeakReference alcWeakRef, out WeakReference assemblyWeakRef) { var context new UnloadablePluginContext(); var assembly context.LoadFromAssemblyName(new AssemblyName(Plugin)); alcWeakRef new WeakReference(context); assemblyWeakRef new WeakReference(assembly); // 卸载上下文 context.Unload(); Console.WriteLine(ALC 已卸载); }}注释说明- 使用WeakReference跟踪 ALC 和程序集的生命周期。- 调用context.Unload()标记 ALC 为可卸载状态但实际释放发生在 GC 回收时。- 在作用域结束后强制 GC 回收验证 ALC 和程序集被彻底释放。这避免了内存泄漏适用于长期运行的插件系统。## 高级议题冲突解决与共享类型### 类型加载冲突当主程序和插件通过不同 ALC 加载相同类型的程序集时CLR 会将其视为不同的类型。例如主程序中的ILogger接口和插件中的ILogger接口即使代码相同不兼容。解决方案包括-共享接口程序集将公共接口放在一个独立的程序集中由默认上下文加载。-使用弱引用或动态调用通过dynamic或反射避免强类型绑定。### 依赖解析链ALC 的Load方法可以实现自定义依赖解析策略。例如从 NuGet 缓存或远程服务器加载程序集csharpprotected override Assembly Load(AssemblyName assemblyName){ // 尝试从自定义缓存加载 string cachePath GetCachePath(assemblyName); if (File.Exists(cachePath)) return LoadFromAssemblyPath(cachePath); // 回退到默认 return AssemblyLoadContext.Default.LoadFromAssemblyName(assemblyName);}## 总结AssemblyLoadContext是 .NET 中实现程序集隔离和可插拔设计的核心工具。通过自定义 ALC我们可以- 在进程内加载多个版本的程序集避免“DLL地狱”。- 构建插件系统支持动态安装、卸载和升级。- 控制程序集加载源增强安全性和灵活性。然而使用 ALC 也需注意类型隔离可能带来兼容性问题卸载需要谨慎处理无引用性能开销略高于默认加载。在实际项目中应结合场景权衡使用。掌握 ALC 原理能让你的 .NET 应用具备更强的模块化能力。

相关新闻

innerHTML和innerTest的区别

innerHTML和innerTest的区别

innerHTML和innerTest的区别 innerHTML如果后面是js代码&#xff0c;则会当做js代码来执行&#xff0c;但在innerTest后面的js代码会被当做普通 文本来输出<style type"text/css">#div_01{background-color: aqua;width: 300px;height: 300px;border: 1px blac…

2026/7/28 18:30:08阅读更多 →
【普通人AI入门指南】:3天掌握5个零代码AI工具,错过这波红利再等5年?

【普通人AI入门指南】:3天掌握5个零代码AI工具,错过这波红利再等5年?

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;普通人如何拥抱AI AI不再是工程师或数据科学家的专属工具&#xff0c;它正以极低门槛融入日常——从手机里的语音助手、购物平台的个性化推荐&#xff0c;到写作辅助、图像生成和日程智能管理。普通人无…

2026/7/28 18:30:08阅读更多 →
百度页面

百度页面

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>百度</title><style type"text/css">div{text-align: center;font-size: 14px;}.ngv,.bk{height: 60px;}.txt{width: 420px;height: 25px;}.bd{width…

2026/7/28 18:30:08阅读更多 →
华为非AI方向笔试真题 7月24号【最优河堤加固方案】

华为非AI方向笔试真题 7月24号【最优河堤加固方案】

最优河堤加固方案(C/Py/Java/Js/Go)题解华为笔试真题 7月24号 非AI方向第一题 100分题型题目内容 一个数组代表河堤的高度&#xff0c;堤坝是等长、等宽的&#xff0c;现在需要在不超过最大预算的前提下&#xff0c;尽可能的加固河堤使最低高度&#xff0c;所有加固的土只能通过…

2026/7/29 2:10:16阅读更多 →
零基础学编程真的不难?3类被92%新手忽略的认知陷阱,AI时代必须避开的4个致命误区

零基础学编程真的不难?3类被92%新手忽略的认知陷阱,AI时代必须避开的4个致命误区

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;零基础学编程真的不难&#xff1f;AI时代的学习真相 过去十年&#xff0c;编程常被塑造成一道高耸的智力门槛——需要数学天赋、逻辑训练和数年苦修。而今天&#xff0c;AI正悄然重写这条学习路径&#xff1a…

2026/7/29 2:10:16阅读更多 →
AI大模型应用开发实战:从Python环境搭建到DeepSeek API调用

AI大模型应用开发实战:从Python环境搭建到DeepSeek API调用

AI大模型应用开发全流程实战&#xff1a;从环境搭建到DeepSeek模型调用最近在AI大模型应用开发过程中&#xff0c;很多开发者反馈环境配置是最容易卡壳的环节。本文将从LLM基础认知出发&#xff0c;通过完整的Python环境搭建、FastAPI后端开发&#xff0c;到实际调用DeepSeek模…

2026/7/29 2:10:16阅读更多 →
2026中国电子元器件分销行业格局:谁在领跑,谁在追赶

2026中国电子元器件分销行业格局:谁在领跑,谁在追赶

中国电子元器件分销行业正在经历一轮深层洗牌。2026年AI基建需求爆发、存储芯片缺货、国产替代加速三重因素叠加&#xff0c;行业格局正在重塑。这篇文章从行业分析视角&#xff0c;梳理当前分销赛道的主要玩家和竞争维度。行业格局的三个梯队&#xff1a;梯队代表平台核心特征…

2026/7/29 2:10:16阅读更多 →
MOSFET选型与驱动电路设计实战指南:从核心参数到PCB布局

MOSFET选型与驱动电路设计实战指南:从核心参数到PCB布局

1. 项目概述&#xff1a;为什么MOSFET值得你花时间&#xff1f;如果你在玩单片机、做电源&#xff0c;或者捣鼓任何带开关功能的电子玩意儿&#xff0c;迟早会碰到一个绕不开的坎——MOSFET。我第一次被它“教育”是在大学做智能车&#xff0c;用单片机IO口直接驱动电机&#x…

2026/7/29 2:10:15阅读更多 →
2026无人机场品牌深度解析:华测AH50自动巡检系统应用指南

2026无人机场品牌深度解析:华测AH50自动巡检系统应用指南

三伏天里&#xff0c;输电线路巡检员顶着烈日翻山越岭&#xff0c;一趟巡检下来衣服全湿透&#xff0c;还未必能发现杆塔上的隐蔽缺陷。据《中国地理信息产业发展报告&#xff08;2025&#xff09;》显示&#xff0c;我国地理信息产业总产值近5年复合增长率为5.6%&#xff0c;近…

2026/7/29 2:08:15阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

&#x1f539; 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具&#xff0c;凭借本地离线运行、可视化图形操作和任务自动化三大核心特性&#xff0c;赢得了众多用户的青睐。与普通在线对话AI工具不同&#xff0c;它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接&#xff0c;是用激光束对阀座壳体&#xff08;通常为不锈钢或铝合金&#xff09;进行密封焊接&#xff0c;使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX&#xff1a;三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停&#xff1f;用 interrupt 给它设个“关卡“&#xff01; 在构建复杂的 Agent 系统时&#xff0c;我们经常会遇到这样的场景&#xff1a;Agent 正在执行一个多步骤的任务&#xff0c;比如“下单购买商品”&#xff0c;但执行到一半时&#xff0c;我们…

2026/7/29 0:01:46阅读更多 →
自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

近日&#xff0c;国际专注开放式技术研发的声学品牌Nank南卡&#xff0c;正式官宣实力艺人曾舜晞担任品牌代言人。消息一经发出便轰动全网。为什么耳机品牌不选择流量明星、老牌歌手&#xff1f;而且是选择曾舜晞&#xff1f;让我们一起来探索一下&#xff01;比起短期的流量&a…

2026/7/29 0:01:46阅读更多 →
【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:01:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →