You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何引用Roslyn动态生成的程序集?重运行时抛出异常

解决Roslyn动态生成程序集重启后加载失败的问题

这个问题我之前帮好几个开发者排查过,核心原因大多是程序集加载上下文不匹配或者生成路径没被CLR正确识别,下面给你拆解几个靠谱的解决方案:

一、先排查基础路径问题

首先确认你生成的dll和pdb文件确实在指定的tempDir路径里,而且重启应用后这个目录没被系统清理(比如系统临时目录经常会在进程退出后自动删文件)。手动去路径下看看文件是否存在,权限是不是正常——有时候系统权限会导致CLR读不到文件。

二、用正确的姿势加载程序集

重启后动态生成的程序集不在CLR默认的探测路径里,直接Assembly.Load("RunTimeRules.XRefRule")肯定会失败,试试这两种方法:

1. 直接通过文件路径加载

最稳妥的方式就是指定完整路径加载:

var assemblyPath = Path.Combine(tempDir, "RunTimeRules.XRefRule.dll");
var assembly = Assembly.LoadFrom(assemblyPath);

注意LoadFrom会把程序集加载到专属的加载上下文里,如果你的动态程序集还有其他依赖,得确保依赖项也能被找到(比如放在同一个目录)。

2. 订阅程序集解析事件

如果没法硬编码路径,可以给当前AppDomain加个解析事件,当CLR找不到程序集时,手动从你的生成目录加载:

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    var assemblyName = new AssemblyName(args.Name);
    var assemblyPath = Path.Combine(tempDir, $"{assemblyName.Name}.dll");
    if (File.Exists(assemblyPath))
    {
        return Assembly.LoadFrom(assemblyPath);
    }
    return null;
};

这样不管什么时候需要加载这个动态程序集,CLR都会触发这个事件,你就能在里面指定加载路径了。

三、生成程序集时的细节优化

用Roslyn的compilation.Emit时,这几个细节能避免后续加载踩坑:

  • 确保生成的程序集名称和你后续加载时用的完全一致(包括大小写,Linux/macOS环境下路径是区分大小写的)
  • 如果动态程序集依赖其他程序集,编译时一定要把这些依赖加入到compilation的引用中,比如:
var compilation = CSharpCompilation.Create("RunTimeRules.XRefRule")
    .WithReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
    // 加上你需要的其他依赖引用
    .WithSyntaxTrees(yourSyntaxTree);

这样生成的程序集才不会有依赖缺失,重启加载时就不会因为找不到依赖报错了。

四、避开临时目录的坑

如果你用的是Path.GetTempPath()这类系统临时目录,要注意很多系统会在进程退出后自动清理临时文件。建议把生成的程序集放到应用专属的持久化目录,比如:

var appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var assemblyDir = Path.Combine(appDataDir, "YourAppName", "DynamicAssemblies");
Directory.CreateDirectory(assemblyDir); // 确保目录存在,不存在就创建

这样程序退出后文件不会被自动删掉,重启时也能正常读取。


内容的提问来源于stack exchange,提问作者Gopi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:06:20