.NET Core动态编译控制台程序存盘运行TypeLoadException问题求助
问题描述
我们通过动态生成代码创建.NET Core控制台应用,使用以下代码编译:
var csharpParseOptions = new CSharpParseOptions(LanguageVersion.Latest); csharpParseOptions = csharpParseOptions.WithPreprocessorSymbols(new[] { "TRACE", "DEBUG" }); var syntaxTree = CSharpSyntaxTree.ParseText(code, options: csharpParseOptions); var compilationUnitSyntax = syntaxTree.GetCompilationUnitRoot(); var options = new CSharpCompilationOptions(OutputKind.ConsoleApplication, optimizationLevel: OptimizationLevel.Debug, platform: Platform.X64) .WithModuleName("TestConsole") .WithMetadataImportOptions(MetadataImportOptions.All) .WithDeterministic(true) .WithConcurrentBuild(true); var csharpCompilation = CSharpCompilation.Create(@"TestConsole", syntaxTrees: new[] { syntaxTree }, references: references, options: options);
通过内存加载生成的程序集时运行正常:
using (var memoryStream = new MemoryStream()) { var emitResult = csharpCompilation.Emit(memoryStream); memoryStream.Position = 0; _assembly = Assembly.Load(memoryStream.ToArray()); }
但将程序写入磁盘后运行,会抛出以下异常:
System.TypeLoadException: Could not load type 'System.Object' from assembly 'System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' because the parent does not exist.
将相同代码复制到空控制台项目可正常运行,但生成的可执行文件更大,求解决思路。
解决思路
- 补充完整框架依赖引用:动态编译时的
references集合大概率只包含部分核心库,而空控制台项目会自动引入完整的.NET Core框架依赖。需明确添加System.Private.CoreLib、System.Runtime等基础核心库的引用,或通过SDK提供的API获取完整框架引用集合,避免手动挑选引用导致的依赖缺失。 - 指定正确目标框架标识:在
CSharpCompilationOptions中通过.WithTargetFramework(TargetFrameworkMoniker.Parse(".NETCoreApp,Version=v6.0"))设置匹配的目标框架,确保编译后的程序集能正确识别运行时的依赖查找路径。 - 配置自包含部署输出:如果需要独立运行的可执行文件,参照空控制台项目逻辑,在编译或后续步骤中配置自包含部署,将必要的运行时文件一并输出到磁盘目录。空项目的大体积文件正是因为包含了运行时,动态编译时需手动补充这部分依赖,保证程序运行时能找到所有核心库。
- 调整元数据导入选项:当前设置的
MetadataImportOptions.All可能导致元数据引用异常,尝试改为MetadataImportOptions.Default,减少不必要的元数据导入,确保核心类型的引用路径正确。 - 验证输出文件完整性:使用
csharpCompilation.Emit输出到磁盘时,需确保所有依赖的程序集也被复制到同一目录。内存加载时CLR会借助当前应用域的依赖解析机制自动找到所需库,但独立运行时必须保证依赖文件存在于程序目录或系统运行时路径。
内容的提问来源于stack exchange,提问作者user2807725
相关产品推荐
相关产品推荐

