roslynscriptcs

scriptcs hosting - Advantages over Roslyn


If I want to support scripting in my application, does scriptcs offer any particular advantages over just using the plain vanilla Roslyn script engine?


Solution

  • Unfortunately there's not much documentation on hosting scriptcs yet, but I'll try to give you a short summary.

    Hosting scriptcs in your application provides several features that vanilla Roslyn doesn't:

    Pluggable Engines

    While scriptcs comes with the Roslyn and Mono engines by default, you can easily replace it with another engine, i.e. F#, LOLcode or even Brainfuck.

    Pre-processing

    scriptcs will process your scripts and extract things like references (#r) and load other scripts (#load). There was also recently introduced custom ILineProcessors which lets you hook into the pipeline for custom processing. An example processor could look like this:

    public class GistLineProcessor : DirectiveLineProcessor
    {
        protected string DirectiveName
        {
            return "gist";
        }
    
        protected override bool ProcessLine(IFileParser parser, FileParserContext context, string line)
        {
            var gistId = GetDirectiveArgument(line);
    
            var gistContents = DownloadGistContents(gistId);
    
            parser.ParseScript(gistContents, context);
    
            return true;
        }
    
        private static string DownloadGistContents(string gistId)
        {
            // Download gist contents...
        }
    }
    

    This processor will download a gist and execute it as part of your script, i.e. #gist 12345678.

    NuGet integration

    scriptcs has integration with NuGet. This means that if you want scripts to be able to use NuGet packages, just install them and they will automatically be loaded from within the packages folder.

    Script packs

    Script packs is scriptcs' way to remove boilerplate code. They can import namespaces, reference assemblies and expose functionality to scripts through Require<T>(). See Martin Doms' excellent blog post about building a scriptcs script pack. For a comprehensive list of available script packs, see Script packs master list.

    REPL

    As you probably know, scriptcs has a REPL. This can be reused in your own application to provide an interactive scripting session.

    Debugging

    Using the vanilla Roslyn script engine, you can't debug scripts very easily. scriptcs gives you the ability to debug scripts with source mapping through #line directives inserted during pre-processing.


    I may have forgotten something, but these are the main points for choosing scriptcs over vanilla Roslyn. When it comes to the actual hosting, you have two options:

    ScriptCs.Core

    This is a super lightweight library that contains the core components of the scriptcs pipeline. However, it doesn't contain implementations for IScriptEngine (the engine that actually executes code) and IInstallationProvider (the component that installs packages, i.e. NuGet), these live in ScriptCs.Hosting and ScriptCs.Engine.Roslyn. If you use this library, you will have to do all the wire-up of the components yourself and you also need to provide an implementation for the engine and the package installer.

    ScriptCs.Hosting

    ScriptCs.Hosting is a convenience layer for hosting scriptcs in an application. It's used internally in scriptcs.exe and does all the wire-up of the components (via Autofac) for you. It contains the NuGet implementation for the package installer and has a dependency on ScriptCs.Engine.Roslyn by default. This is the preferred way to host scriptcs as it provides a ScriptServicesBuilder to easily replace scriptcs' internal services. See scriptcs' Program.cs for example usage.

    This could sound confusing so if you have questions, please ask on JabbR, Github or on the Google Group.