Skip to content

Integrate with .net program

Jing Lu edited this page Jun 18, 2013 · 82 revisions

ReoScript provides the ability to execute script in your application. It usually could be used in the following cases:

  • Application with script execution

    Software with Macro or Script execution is required to be available for end-user. (like VBA in Excel)

  • Script to be ran under a native library that is provided by your Application

    You have a library written in .NET program, and you want to your end-user can use them by writing script.

  • Console Script Execution

    Some batch process program, Daily build, File publish or something else. You are able to make extensions for ReoScript in .NET program, and writing and running the script in console.

Setup ReoScript

  1. Download ReoScript binary or build source file. Add the following DLLs into reference list of your project.

     Antlr3.Runtime.dll
     Unvell.ReoScript.dll
    
  2. Import the following namespace

     using Unvell.ReoScript;
    
  3. Create ScriptRunningMachine and keep the instance

     ScriptRunningMachine srm = new ScriptRunningMachine();
    
  4. Run script from different source

    • Run script in text

        srm.Run("console.log('hello world');");
      
    • Run script from internal resource

        using(MemoryStream ms = new MemoryStream(Resources.script)) {
            srm.Load(ms);
        }
      
    • Run script from specified file

        srm.Load("C:\\scripts\\main.rs");
      
    • Run script from specified stream (could be a network, or unzipped stream etc.)

        srm.Load(new NetworkStream(...));
      

    See ScriptRunningMachine.

Practices to integrate ReoScript in your application

There are two practices to integrate ReoScript in your application.

  1. Manual Mode (writing wrapper objects, properties or methods)
  2. Automatic Mode (using DirectAccess)

Manual Mode (writing wrapper objects, properties or methods)

To connect the two worlds between script and .NET, the wrapper objects, properties and methods may be necessary to be written.

              +-----------------------------------------------------+
              |                       Script                        |
              |    +-------------------------------------------+    |
              +--- |  Wrapper objects, properties and methods  | ---+        <--- You may have to do
              |    +-------------------------------------------+    |
              |                  .NET Application                   |
              +-----------------------------------------------------+

I called this as 'Manual Mode' because anything you want to provide for script are all controllable precisely. Your end-user can only uses the functions that you want to be used. This practice is more safer and stable than Automatic Mode, it is also recommended usage if you are planning to make script execution is available to your end-user.

To write wrapper objects, properties and methods, the following classes you may need to use in .NET program.

About Global Object

Once the script execution context(ScriptRunningMachine) is created, ReoScript keeps an global object until the context is destroying. Global object can be understood as a root object in the context, all objects to be used in script should be added into global object firstly. Once the object(even a function) has been added into global object, it will be available to all scopes of functions in a context. (See GlobalObject)

Add own customized function

If you want to add a function for script, you may create a NativeFunctionObject instance and add it into global object. For example:

ScriptRunningMachine srm = new ScriptRunningMachine();
srm["myfunc"] = new NativeFunctionObject("myfunc", (ctx, owner, args) => {
    Console.WriteLine('myfunc called!');
});

Now use this function in script:

myfunc();

The text will be printed out in console:

myfunc called!

In ReoScript, everything even a function are objects, and one object can be added into another object as its property by a given name. For example:

var obj = new Object();         // create an object instance
var func = function() { };      // create an anonymous function
obj.myfunc = func;              // set func into obj as its property (now it more likes a method)

See NativeFunctionObject.

Automatic Mode (using DirectAccess)

All the objects, types, properties and methods which requested to use in script are all mapped to .NET Runtime automatically by ReoScript engine. In this Automatic Mode, the intermediate wrapper objects is unnecessary.

              +-----------------------------------------------------+
              |                       Script                        |
              |    +-------------------------------------------+    |
              +--- |     .NET Reflection / ReoScript Engine    | ---+        <--- You don't have to do
              |    +-------------------------------------------+    |
              |                  .NET Application                   |
              +-----------------------------------------------------+

DirectAccess allows script to access the property of .NET object by .NET Reflection Technology. Although this feature can be a very simple way to integrate ReoScript, but it may also became a potential risk at script run-time. Unless you uses script inside your application, please consider about the Manual Mode as 'My Suggestion'.

(See more DirectAccess)

My Suggestion

Although ReoScript provides DirectAccess mechanism to access .NET object directly, it is recommended that writing wrapper objects, properties and methods if you are planning to make script execution to be available for your end-user.

For example, assuming there is a .NET object with one method and property:

public class Application
{
    public void Start() { ... }
    public string Name { get; set; }
}

With DirectAccess, you would be able to call 'Start' method from script directly:

var app = new Application();
app.start();

Or access its property like:

app.name = 'stuff';

But if you reformed your .NET program, like renaming method, the script will be unavailable. For usability it is recommended that writing wrapper method for your application and script.

  1. Create wrapper object - create a class inheriting from ObjectValue, keep an instance of original object. And add methods that you want to provide for script.

     public class ApplicationObject : ObjectValue 
     {
         public Application Application { get; set; }
    
         public ApplicationObject() {
             // keep original instance
             this.Application = new Application();
    
             // add wrapper method
             this["start"] = new NativeFunctionObject("start", (ctx, owner, args)=> {
                 this.Application.Start();
             });
         }
     }
    

    About function extension please see NativeFunctionObject.

  2. Import this wrapper object type into script context

     // prepare srm
     ScriptRunningMachine srm = new ScriptRunningMachine();
    
     // import .Net type into srm
     srm.ImportType(typeof(ApplicationObject), "Application");
    

Then the Application class will be available to script.

var app = new Application();
app.start();