System.CodeDom.Compiler编译IScript未定义、类型转换失败问题求助
问题根因与解决方案
错误核心逻辑
首先明确两个报错的底层原因:
- 报
Type 'IScript' is not defined:动态编译的代码无法识别主程序中定义的IScript接口 - 重复定义接口后转换失败:CLR中类型由「程序集+命名空间+类型名」唯一标识,动态代码里重新定义的
IScript和主程序的IScript是完全不同的两个类型,强制转换必然失败,绝对不能在动态拼接代码里重复定义IScript接口。
具体修复步骤
第一步:验证
IScript的可访问性与命名空间- 保证
IScript是全局Public修饰,不能嵌套定义在其他类、模块内部,不能用Friend修饰 - 检查VB项目属性的「根命名空间」配置:
如果你的IScript直接定义在项目根命名空间下,GetType(IScript).Namespace会返回空值,此时你拼接的Imports& interfaceNamespace等价于无效代码,两种解决方案二选一:- 给主程序的
IScript套一层显式命名空间,例如:
此时Namespace MyScriptHost Public Interface IScript Property theDataTable As System.Data.DataTable Sub DoWork() End Interface End NamespaceGetType(IScript).Namespace会正常返回MyScriptHost,Imports语句生效。 - 或者在动态拼接代码的Implements语句处直接写全类型名,例如:
builder.AppendLine(" Implements 你的根命名空间.IScript") builder.AppendLine(" Public Property theDataTable As DataTable Implements 你的根命名空间.IScript.theDataTable") builder.AppendLine(" Public Sub DoWork() Implements 你的根命名空间.IScript.DoWork")
- 给主程序的
- 保证
第二步:验证程序集引用有效性
调试时断点检查Assembly.GetExecutingAssembly().Location的返回值,确认是当前运行主程序的exe/dll的正确物理路径:
如果你是在ASP.NET、单元测试、单文件发布场景下,该路径可能指向临时目录而非实际编译的主程序集,可替换为以下代码获取程序集引用:parameters.ReferencedAssemblies.Add(GetType(IScript).Assembly.Location)第三步:修复动态代码中的隐藏语法错误
你拼接的代码里有一行笔误:SshClient.Disconnect()是类名调用静态方法,实际应该调用实例的Disconnect方法,改为sshClient.Disconnect(),否则就算接口识别成功也会报编译错误。
验证方式
修复后可先把拼接完成的全部代码输出到文本文件,手动拷贝到VB项目中编译,就能快速定位是引用问题还是语法问题。
内容的提问来源于stack exchange,提问作者Jaco le Grange
相关产品推荐
相关产品推荐

