C#怎么实现动态加载DLL C#如何在运行时动态加载和卸载程序集调用其中的方法【进阶】

落丽姑娘_5559

落丽姑娘_5559

2026-04-01

461人浏览

原创

assemblyloadcontext(alc)是.net core/.net 5+中唯一可卸载程序集的机制,需创建iscollectible=true的非默认alc,通过其loadfromassemblypath加载,并用委托或executeinloadcontext跨上下文调用,卸载前须清除所有引用并确保无后台线程或事件残留。

c#怎么实现动态加载dll c#如何在运行时动态加载和卸载程序集调用其中的方法【进阶】

用 AssemblyLoadContext 加载 DLL,不是 Assembly.LoadFrom

直接调用 Assembly.LoadFrom 或 Assembly.LoadFile 会导致程序集永久驻留——哪怕你把它设为 null、清空引用、触发 GC,它也卸载不掉。这是 .NET Core / .NET 5+ 最常踩的坑:你以为卸载了,其实没卸。

真正可卸载的路径只有一条:AssemblyLoadContext(ALC)。它把程序集隔离在独立上下文中,支持显式卸载(Unload()),前提是这个 ALC 是“非默认”的(即构造时传 isCollectible = true)。

  • AssemblyLoadContext.Default 永远不可卸载,所有传统加载方式默认都走它
  • 必须新建一个 collectible ALC:var alc = new AssemblyLoadContext(isCollectible: true)
  • 加载必须通过该 ALC 的 LoadFromAssemblyPath 方法,不能用静态 Assembly.Load* 系列
  • 加载后,类型反射、创建实例、调用方法,全部要在该 ALC 内完成,跨 ALC 直接传类型会报 System.Runtime.Serialization.SerializationException 或类型不匹配

调用 DLL 中的方法前,得先解决“跨 ALC 类型访问”问题

你不能直接写 var obj = Activator.CreateInstance(type) 然后调用其方法——如果 type 来自 collectible ALC,而当前代码在默认 ALC,.NET 会拒绝操作,报错类似:Cannot load type 'XXX' from assembly 'YYY' because it is not in the same context。

可行方案只有两个,且都绕不开“边界代理”:

  • 用 MarshalByRefObject + 远程激活(仅限 .NET Framework,.NET Core+ 已移除 Remoting 支持)
  • 在目标 ALC 内部定义一个“桥接器”类(继承 MarshalByRefObject 不再有效),然后通过接口抽象 + AssemblyLoadContext.GetLoadContext(assembly).ExecuteInLoadContext 执行闭包逻辑
  • 更常用的是:把要调用的逻辑封装成 Func<object></object> 或 Action 委托,在 ALC 内部构造并返回,再在外部调用——委托本身是跨 ALC 安全的

示例关键片段:

C#
C#

"避开 C# 常见错误——空陷阱、异步陷阱、LINQ 陷阱及资源泄漏。"

下载
var alc = new AssemblyLoadContext(isCollectible: true);
var asm = alc.LoadFromAssemblyPath(@"plugin.dll");
var entryType = asm.GetType("Plugin.Entry");
var entry = alc.LoadFromAssemblyPath(@"plugin.dll").CreateInstance("Plugin.Entry");
// ❌ 错误:entry 是 collectible ALC 中的对象,直接调用方法会失败
// ✅ 正确:用反射 + Invoke,或提前在 ALC 内准备好可序列化/委托化的入口
var method = entryType.GetMethod("DoWork");
method.Invoke(entry, null); // ⚠️ 仍可能失败,取决于方法内部是否引用其他 collectible 类型

卸载失败?检查是否有任何托管对象还在引用该 ALC

alc.Unload() 不是立即生效的异步操作,它会发起卸载请求,但只有当该 ALC 中所有对象都被 GC 回收、且无任何强引用残留时,才会真正完成。常见卡住原因:

  • 你在默认 ALC 中保存了来自该 ALC 的 Type、MethodInfo、Delegate 实例(它们隐式持有 ALC 引用)
  • 插件 DLL 启动了后台线程、注册了事件(尤其是静态事件)、开启了 Timer,且未在卸载前清理
  • 使用了 AssemblyLoadContext.Default.Resolving 事件,并在其中返回了该 collectible ALC 中的程序集(形成循环引用)
  • 日志框架(如 Serilog、NLog)缓存了插件中的类型名或属性,导致引用泄漏

验证是否卸载成功:调用 alc.Unload() 后,手动触发 GC.Collect(); GC.WaitForPendingFinalizers();,再检查 alc.Assemblies 是否为空、alc.IsUnloaded 是否为 true。

.NET Framework 下没有 AssemblyLoadContext,只能靠 AppDomain(已废弃)

.NET Framework 4.x 虽然支持 AppDomain 隔离和卸载,但它在 .NET Core / .NET 5+ 中被彻底移除,且即便在旧框架下也极不稳定:AppDomain 卸载后无法完全回收内存,容易引发 Cannot unload an AppDomain 或句柄泄漏。微软官方已标记为“不推荐用于新开发”。

如果你必须兼容老框架,唯一较稳妥的做法是:进程外加载(启动子进程运行插件,通过 IPC 通信),而不是进程内动态加载。否则,所谓“卸载”,基本等于“等进程退出”。

现代项目请坚定使用 AssemblyLoadContext,并接受它的约束:一切跨 ALC 操作必须显式桥接、所有资源必须主动释放、卸载不是命令而是协作结果。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c#

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c#是什么意思
c#是什么意思

C#是一种通用的面向对象编程语言,它在.NET框架上运行,可用于开发各种类型的应用程序。本专题为大家提供c#相关的各种文章、以及下载和课程。

2023.08.08

1012

5

什么是c#
什么是c#

C#(读作C Sharp)是一种现代的、通用的、面向对象的编程语言。它由微软公司开发,于2000年首次发布,主要用于开发Windows桌面应用程序、Web应用程序、移动应用程序以及游戏开发等领域。C#是一种类型安全和托管的编程语言,它结合了C++的强大性能和C语言的简单易学特点,并引入了许多新的特性和概念,如委托、属性、泛型和异步编程等,以提高开发效率和代码可维护性。

2023.08.31

2951

3

C#中base关键字的用法
C#中base关键字的用法

在C#中,base关键字用于访问当前类的基类成员,这包括基类的字段、属性、方法、构造函数、索引器以及事件。想了解更多C#的相关内容,可以阅读本专题下面的文章。

2024.03.13

885

8

C#Task用法
C#Task用法

Task在C#中是用于表示异步操作的对象,它位于System.Threading.Tasks命名空间中。想了解更多C#中各种用法的相关内容,可以阅读本专题下面的文章。

2024.03.14

2615

11

C# 并发与异步编程
C# 并发与异步编程

本专题系统讲解 C# 异步编程与并发控制,重点介绍 async 和 await 关键字、Task 类、线程池管理、并发数据结构、死锁与线程安全问题。通过多个实战项目,帮助学习者掌握 如何在 C# 中编写高效的异步代码,提升应用的并发性能与响应速度。

2026.02.03

312

18

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

2026.02.06

389

20

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

2026.03.11

631

24

C# Unity游戏开发与ECS架构实践
C# Unity游戏开发与ECS架构实践

本专题聚焦 C# 在 Unity 游戏开发中的应用,系统讲解 ECS(Entity-Component-System)架构设计、游戏对象管理、性能优化与内存控制策略。通过实际游戏案例,帮助开发者构建高性能、结构清晰的游戏系统,提高游戏开发效率与运行性能。

2026.04.13

329

20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习