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

CSharpScript使用外部定义类型时同类型转换失败问题求助

这个问题我太熟了!你猜的没错,就是程序集加载上下文不一致搞的鬼——你的主程序和CSharpScript各自加载了一份Common.dll,哪怕它们是同一个文件,CLR也会把这两个程序集里的Arguments和Output当成完全不同的类型,自然就转不过去了。

核心原因拆解

看错误信息里的两个Common.Arguments:一个带具体文件路径,一个是程序集版本标识,这说明主程序是在默认的程序集加载上下文中加载的Common.dll,而CSharpScript在自己独立的加载上下文里又重新加载了一遍。CLR判断类型是否相同的标准是程序集实例+类型全名,所以哪怕类型代码完全一样,来自不同程序集实例的类型就是不兼容的。

解决方案

方法1:复用主程序已加载的程序集(最简单)

修改脚本选项的构建代码,直接把主程序中已经加载的Common程序集实例传给脚本,而不是让脚本自己重新加载:

首先确保你的代码引用了System.Reflection命名空间,然后替换原来的AddReferences代码:

// 获取主程序中已加载的Common程序集实例
var commonAssembly = typeof(Arguments).Assembly;
// 将这个实例添加到脚本选项中,让脚本复用它
options = options.AddReferences(commonAssembly);

这样脚本就会和主程序使用同一个程序集实例,类型自然就能匹配转换了。

方法2:用AssemblyLoadContext统一加载上下文(适配特殊场景)

如果方法1没生效(比如涉及到复杂的部署或插件场景),可以显式使用默认的AssemblyLoadContext来加载Common.dll,确保脚本和主程序处于同一个加载上下文:

先添加System.Runtime.Loader的引用,然后修改代码:

using System.Runtime.Loader;

// 获取Common.dll的实际磁盘路径
var commonAssemblyPath = typeof(Arguments).Assembly.Location;
// 用默认加载上下文加载程序集,避免脚本创建新的加载上下文
var commonAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(commonAssemblyPath);
// 添加到脚本选项
options = options.AddReferences(commonAssembly);

额外优化建议

如果你的脚本逻辑不需要专门定义TestClass,可以直接把逻辑写成表达式,减少不必要的类型依赖:

// 直接创建返回Output的脚本,无需定义类
var script = CSharpScript.Create<Output>(@"
    return new Output() { Success = arguments.Text == text };
", options: options, globalsType: typeof(Parameters));

// 运行后直接得到Output,无需强制转换
Output output = script.RunAsync(globals: parameters).Result.ReturnValue;

这样代码更简洁,还能避免脚本中定义类带来的额外类型匹配问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:09:30