以下是尼科斯在科隆举行的 XBase.Future 2017 会议上的演讲内容。
本次会议的示例在安装 X# 时保存在 c:\Users\Public\Documents\XSharp\Scripting 文件夹中。
•运行时的动态特性
o可扩展性和灵活性
o用户自定义行为
•平台的独立性
o在脚本中定义的系统操作
•行为即数据
o存储在文件、数据库和云端
o运行时更新
•快速原型设计
•表达式评估
o内置解释器
o自带功能
o简单表达或完整陈述
•无项目的源文件
o单个文件(单个脚本可加载多个数据源)
o无需完整的集成开发环境或 SDK
o无需集成开发环境的动态编译
o复杂结构、类的定义
•Roslyn 脚本引擎
oC# 脚本
•独立表达式
o无 START 函数
o全局语句、表达式
o与宏编译器类似(但并不相同!)。
o主机对象维持状态
•允许使用复杂的声明
o可以声明类型、函数
o没有命名空间!
•外部引用
o加载组件
o无法隐式访问主机程序集
o无隔离(例如单独的 AppDomain)
•读取-评估-打印循环 (REPL)
•控制台应用程序
•返回值将打印到控制台
o具有漂亮的格式!
•保持上下文
•声明局部变量
•可加载程序集和脚本文件
o.PRGX 扩展
o#R 指令
o#LOAD 指令
•可从命令行运行脚本
oXsi.exe <script.prgx>
•向脚本传递命令行参数
oXsi.exe <script.prgx> <arg> ...
•将 xsi.exe 设置为 .prgx 的默认应用程序
o也会创建文件关联,但没有参数
o编辑注册表中的文件关联
•手动设置文件关联
oassoc, ftype
•调用时不使用 .prgx 扩展名
oPATHEXT
•不在控制台运行?
o无法使用 xsi.exe,因为它是一个控制台应用程序
•每个脚本都被编译为“子任务”
oRoslyn 术语
•在 xsi 提示符下输入的每一行都会创建一个新的子任务
o继承之前提交的子任务
o之前已声明的变量仍然可见
•不能直接检查
o“SELF“ 和 ”SUPER" 无法访问
•语句在全局对象上下文中执行
•由 xsi.exe 生成
oInteractiveScriptGlobals 类
•提供对命令行参数的访问
•带有漂亮格式选项的打印功能
•脚本中声明的 LOCAL 真的是局部的吗?
o在方法之外声明时则不会
o它们会成为 submission 类的字段
•那么 FUNCTION 和 PROCEDURE 呢?
o它们会成为 submission 类的方法
•声明类型?(类型、结构、枚举)
o它们会成为 submission 类的嵌套类型
o不能有扩展方法!
•为您的应用程序添加脚本功能!
•引用脚本托管和代码分析程序集
oXSharp.CodeAnalysis.dll
oXSharp.Scripting.dll
•重要的命名空间
oLanguageService.CodeAnalysis.Scripting
oLanguageService.CodeAnalysis.Xsharp.Scripting
•运行脚本
oXSharpScript.RunAsync("? 'HELLO'")
o如果源代码有错误,会抛出 CompilationErrorException(编译错误异常)。
•传递参数:globals 对象
•脚本可以访问 globals 对象的 public 成员
oglobals 对象的类型可以是自定义的
•可以将 globals 对象的实例传递给 RunAsync()
oglobals 对象的 public 字段可用于向脚本传递参数
o脚本将把它们作为变量来访问
•脚本可访问 globals 对象的 public 成员
o切记:脚本是在内存中的不同程序集中编译和执行的!
•提供类型访问权限的方法并不优雅
o但对于基于函数的 API 来说,这一点非常出色
o自成一体(Self-contained)、不易出错
•脚本无法直接访问所有应用程序类型
•不是安全措施!
o脚本在同一 AppDomain(动态程序集)中运行
•脚本可以引用程序集
o通过 #R 指令
o通过传递给 RunAsync() 调用的选项
•将脚本可访问的函数和类型移至单独的程序集
o然后脚本就可以引用该程序集了
•可与 globals 对象结合使用
•脚本可以使用 RETURN 语句返回值
o...或独立表达式!
oEvalAsync() 返回该值
oRunAsync() 返回一个 ScriptState 对象,也可以从中获取返回值
•可以检查脚本声明的变量
oRunAsync() 返回的 ScriptState 对象包含用于检查变量的方法
•ScriptState.GetVariable(string name)
•编译错误
o抛出 CompilationErrorException
oRoslyn API 提供对编译信息的访问
o使用 XsharpScript.Create() 创建 script 对象
o使用 script:Compile() 进行编译
•返回诊断信息列表
•运行时错误
o抛出异常
•因为脚本是作为任务(Task)运行的,所以会出现 AggregateException 异常
•e:InnerException 属性包含真正的异常
•默认情况下,脚本会返回 OBJECT
•可指定自定义返回类型
oCreate<T>()
oRunAsync<T>()
oEvaluateAsync<T>()
•预编译脚本
oScript:Compile()
o编译后的脚本可多次运行
o与宏类似
•可使用 script:CreateDelegate() 创建委托
•使用 ngen.exe 生成本地图像
o加快初次编译
o64 位 CLR 必须使用 64 位版本的 ngen!!!
o适用于命令行脚本 (xsi.exe)
•脚本不能像函数一样使用
o不接受参数
•相反,它需要一个全局对象实例
o通过脚本托管对象运行
•额外开销
•但脚本可以对函数进行求值!
oLamda 函数或委托作为返回类型
•提供内存中当前程序集的引用
oAssembly.GetExecutingAssembly()
o不能与 CoreCLR 一起使用
•可使用当前程序集中声明的实体
oFunctions & procedures
o类型(类、结构等)
o命名空间
•需要引用适当的程序集
oMicrosoft.Csharp.dll