Below is the text from the presentation from the session that Nikos did in Cologne during the XBase.Future 2017 conference.
The examples from this session are stored during the installation of X# in the folder c:\Users\Public\Documents\XSharp\Scripting.
•Dynamic behavior at runtime
oExtensibility and flexibility
oUser-defined behavior
•Platform independence
oSystem operations defined in a script
•Behavior as data
oStored in files, database, cloud
oUpdated at runtime
•Rapid prototyping
•Expression evaluation
oBuilt-in interpreter
oSelf-contained functionality
oSimple expressions or full statements
•Source file(s) without a project
oSingle file (multiple sources may be loaded by a single script)
oNo need for a full IDE or SDK
oDynamic compilation without an IDE
oDefinition of complex structures, classes
•Roslyn script engine
oC# scripting
•Standalone expressions
oNo START function
oGlobal statements, expressions
oSimilar to the macro compiler (but not the same!)
oHost object maintains state
•Complex declarations allowed
oTypes, functions can be declared
oNo namespaces!
•External references
oLoading assemblies
oNo implicit access to host assembly
oNo isolation (e.g. separate AppDomain)
•Read-Eval-Print Loop (REPL)
•Console application
•Return values are printed to the console
oWith pretty formatting!
•Maintain context
•Declare LOCAL variables
•Can load assemblies, script files
o.PRGX extension
o#R directive
o#LOAD directive
•Can run scripts from command line
oXsi.exe <script.prgx>
•Passes command-line arguments to scripts
oXsi.exe <script.prgx> <arg> ...
•Setting xsi.exe as default app for .prgx
oAlso creates file association, but without args
oEdit file association in registry
•Manually setting file association
oassoc, ftype
•Invoking without the .prgx extension
oPATHEXT
•Run without console?
oNot possible with xsi.exe since it is a console application
•Every script is compiled into a “submission”
oRoslyn terminology
•Every line given to the xsi prompt creates a new submission
oInherits previous submission
oPreviously declared variables remain visible
•Cannot be inspected directly
o“SELF” and “SUPER” are not accessible
•Statements execute in the context of the global object
•Generated by xsi.exe
oInteractiveScriptGlobals class
•Provides access to command-line arguments
•Print function with pretty formatting options
•Are LOCALs declared in a script really local?
oNot when they are declared outside of a method
oThey become fields of the submission class
•What about FUNCTIONs and PROCEDUREs?
oThey become methods of the submission class
•Declared types? (CLASSes, STRUCTUREs, ENUMs)
oThey become nested types in the submission class
oNot possible to have extension methods!
•Add scripting capabilities to your application!
•Reference the script hosting and code analysis assemblies
oXSharp.CodeAnalysis.dll
oXSharp.Scripting.dll
•Important namespaces
oLanguageService.CodeAnalysis.Scripting
oLanguageService.CodeAnalysis.Xsharp.Scripting
•Run a script
oXSharpScript.RunAsync("? 'HELLO'")
oCompilationErrorException is thrown if the source has errors
•Passing arguments: the globals object
•The script can access public members of the globals object
oThe type of the globals object can be custom
•An instance of the globals object can be passed to RunAsync()
oPublic fields of the globals object can be used to pass arguments to the script
oThe script will access them as variables
•Public members of the globals object are accessible by the script
oRemember: the script is compiled and executed in a different assembly in-memory!
•Not an elegant method to give access to types
oBut excellent for a function-based API
oSelf-contained, not prone to errors
•The script does not have direct access to all application types
•Not a security measure!
oThe script is run in the same AppDomain (in a dynamic assembly)
•Scripts can reference assemblies
oThrough the #R directive
oThrough the options passed to the RunAsync() call
•Move functions and types that should be accessible by the script to a separate assembly
oThe assembly can then be referenced by the script
•Can be used in conjunction with the globals object
•Scripts can return a value with a RETURN statement
o...or from a standalone expression!
oEvalAsync() returns that value
oRunAsync() returns a ScriptState object, from which the return value can also be fetched
•Variables declared by the script can be examined
oThe ScriptState object returned by RunAsync() includes methods to examine the variables
•ScriptState.GetVariable(string name)
•Compilation errors
oCompilationErrorException thrown
oRoslyn API provides access to compilation messages
oCreate script object with XsharpScript.Create()
oCompile with script:Compile()
•Returns list of diagnostic messages
•Runtime errors
oException is thrown
•AggregateException because script is ran as a Task
•e:InnerException property contains the real exception
•By default a script returns OBJECT
•Custom return type can be specified
oCreate<T>()
oRunAsync<T>()
oEvaluateAsync<T>()
•Pre-compile scripts
oScript:Compile()
oCompiled scripts can be ran multiple times
oSimilar to macros
•Delegate can be created with script:CreateDelegate()
•Native image with ngen.exe
oSpeed-up initial compilation
o64-bit version of ngen must be used for 64-bit CLR!!!
oUseful for command-line scripts (xsi.exe)
•A script cannot be used exactly like a function
oDoes not accept arguments
•Instead, it needs a global object instance
oIs run via a script hosting object
•Additional overhead
•But scripts can evaluate to functions!
oLamda functions or delegates as return type
•Provide a reference to current assembly inmemory
oAssembly.GetExecutingAssembly()
oDoes not work with CoreCLR
•Entities declared in current assembly can be used
oFunctions & procedures
oTypes (classes, structures, etc.)
oNamespaces
•Need to reference the proper assembly
oMicrosoft.Csharp.dll