如何在C#程序中嵌入含非托管代码的CLR程序集并运行时加载
嵌入含非托管代码的CLR程序集并运行时加载的实现方案
嘿,你的这个思路完全没问题!把包含非托管代码的CLR程序集作为嵌入资源打包到C#可执行文件里,然后运行时读取字节流加载,是完全可行的方案。我给你补充一些细节和优化点,帮你避免踩坑:
一、先确认嵌入资源的名称是否正确
这是最容易踩坑的环节:你传给GetManifestResourceStream的资源名称必须完全匹配实际的嵌入资源名。可以通过两种方式确认:
- 右键项目 → 属性 → 资源 → 找到你嵌入的DLL,查看它的「资源名称」(通常是项目默认命名空间 + 文件名,如果DLL放在子文件夹里,还要加上文件夹路径,比如
MyNamespace.SubFolder.MyCLRAssembly.dll) - 用代码遍历所有资源名来排查,直接打印出来看:
foreach (var resourceName in Assembly.GetExecutingAssembly().GetManifestResourceNames()) { Console.WriteLine(resourceName); }
二、优化你的加载代码(增加错误处理)
你的基础代码逻辑是对的,但加上错误处理会更健壮,能快速定位问题:
public static Assembly LoadEmbeddedCLRAssembly() { var currentAssembly = Assembly.GetExecutingAssembly(); const string targetResourceName = "MyNamespace.MyCLRAssembly.dll"; using (var resourceStream = currentAssembly.GetManifestResourceStream(targetResourceName)) { if (resourceStream == null) { throw new FileNotFoundException("嵌入的CLR程序集资源未找到,请检查资源名称是否正确", targetResourceName); } byte[] assemblyBytes = new byte[resourceStream.Length]; int totalReadBytes = resourceStream.Read(assemblyBytes, 0, assemblyBytes.Length); // 确保资源被完整读取 if (totalReadBytes != assemblyBytes.Length) { throw new IOException("读取嵌入资源时未获取到完整的程序集数据"); } return Assembly.Load(assemblyBytes); } }
三、非托管代码相关的注意事项
因为你的程序集包含非托管代码,别担心,Assembly.Load(byte[])仍然能正常加载它,CLR会自动处理非托管部分的加载逻辑,但要注意两点:
- 如果非托管代码依赖其他外部DLL,这些依赖要么也一起嵌入到主程序中(同样用资源方式加载),要么确保运行时能在系统路径或程序目录下找到它们
- 如果非托管代码有特定平台依赖(比如x86/x64),你的主C#程序也要设置对应的平台目标(右键项目 → 属性 → 生成 → 平台目标),否则会出现加载失败的情况
四、加载后的使用示例
加载完成后,你可以通过反射调用目标程序集中的类型和方法:
// 加载嵌入的程序集 var loadedAssembly = LoadEmbeddedCLRAssembly(); // 获取目标类型 var targetClassType = loadedAssembly.GetType("MyCLRAssembly.TargetClass"); // 创建实例 var classInstance = Activator.CreateInstance(targetClassType); // 获取并调用目标方法 var targetMethod = targetClassType.GetMethod("TargetMethod"); targetMethod.Invoke(classInstance, new object[] { "参数1", 123 });
内容的提问来源于stack exchange,提问作者user5265160
相关产品推荐
相关产品推荐

