贝利信息

C# 程序集加载方法 C#如何使用Assembly.LoadFile加载DLL

日期:2026-01-25 00:00 / 作者:畫卷琴夢
Assembly.LoadFile仅按绝对路径加载DLL,不解析依赖、不查GAC、不参与绑定上下文,每次调用返回新实例;适合临时独立库,但需手动加载所有依赖,否则易现FileNotFoundException或InvalidCastException。

Assembly.LoadFile 会绕过 GAC 和绑定上下文,只按路径加载

Assembly.LoadFile 是最“直白”的加载方式:它不走 .NET 的程序集解析流程(比如不查 GAC、不触发 AssemblyResolve 事件、不参与当前 AssemblyLoadContext 的依赖管理),纯粹根据你传入的完整文件路径读取并加载 DLL 到当前进程。这意味着它适合临时加载一个独立工具库,但不适合用于有强依赖关系的模块。

常见错误现象:FileNotFoundException 明明文件存在却报找不到;或后续调用类型时抛 InvalidCastExceptionMethodAccessException —— 很可能是因为依赖的其他 DLL 没被自动加载,或同名类型在不同上下文中重复定义。

LoadFile 和 LoadFrom 的关键区别在哪

很多人误以为 Assembly.LoadFrom 只是“带缓存版”的 LoadFile,其实二者语义完全不同:

所以如果你的 DLL 依赖其他本地 DLL,别用 LoadFile —— 它不会帮你“顺手带上”,你得手动用 LoadFileLoadFrom 把每个依赖都显式加载一遍,顺序还得对(先加载依赖,再加载主程序集)。

如何安全地从字节数组或嵌入资源加载 DLL

如果你把 DLL 作为嵌入资源打包进主程序,不能直接用 LoadFile(它只接受路径)。此时应改用 Assembly.Load(byte[])

var bytes = Properties.Resources.MyPlugin;
var asm = Assembly.Load(bytes);

注意:Assembly.Load(byte[]) 加载的是“纯 IL 字节”,它会走标准绑定流程(如检查 GAC、触发 AssemblyResolve),且生成的程序集属于当前 AssemblyLoadContext。这和 LoadFile 的隔离性完全相反。

加载后怎么调用其中的类和方法

加载成功只是第一步。由于 LoadFile 返回的程序集不在默认上下文中,你不能直接写 new MyPlugin.ClassA() —— 编译器根本不知道这个类型。

必须用反射:

var asm = Assembly.LoadFile(@"C:\lib\MyPlugin.dll");
var type = asm.GetType("MyPlugin.ClassA");
var instance = Activator.CreateInstance(type);
var method = type.GetMethod("DoWork");
method.Invoke(instance, null);

真正麻烦的不是加载,而是跨上下文的类型转换和生命周期管理——比如你从 LoadFile 加载的程序集里 new 出的对象,传给主程序时若涉及接口实现,必须确保接口定义在双方都能访问的共享程序集中,否则就是两个“同名不同源”的类型,强制转换必失败。