C#怎么实现动态加载DLL C#如何在运行时动态加载和卸载程序集调用其中的方法【进阶】
AssemblyLoadContextALC是.NET Core/.NET 5中唯一可卸载程序集的机制需创建isCollectibletrue的非默认ALC通过其LoadFromAssemblyPath加载并用委托或ExecuteInLoadContext跨上下文调用卸载前须清除所有引用并确保无后台线程或事件残留。用 AssemblyLoadContext 加载 DLL不是 Assembly.LoadFrom直接调用 Assembly.LoadFrom 或 Assembly.LoadFile 会导致程序集永久驻留——哪怕你把它设为 null、清空引用、触发 GC它也卸载不掉。这是 .NET Core / .NET 5 最常踩的坑你以为卸载了其实没卸。真正可卸载的路径只有一条AssemblyLoadContextALC。它把程序集隔离在独立上下文中支持显式卸载Unload()前提是这个 ALC 是“非默认”的即构造时传 isCollectible true。AssemblyLoadContext.Default 永远不可卸载所有传统加载方式默认都走它必须新建一个 collectible ALCvar 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 执行闭包逻辑更常用的是把要调用的逻辑封装成 Funcobject 或 Action 委托在 ALC 内部构造并返回再在外部调用——委托本身是跨 ALC 安全的示例关键片段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 类型卸载失败检查是否有任何托管对象还在引用该 ALCalc.Unload() 不是立即生效的异步操作它会发起卸载请求但只有当该 ALC 中所有对象都被 GC 回收、且无任何强引用残留时才会真正完成。常见卡住原因 Tellers AI Tellers是一款自动视频编辑工具可以将文本、文章或故事转换为视频。