Thursday, May 5, 2011

Micro Effects in 5 Minutes

The Micro Effects .NET Framework is very close to open release. In my last post, I gave a sneak peak of some of the more advanced features of the framework. A couple of my fellow engineers mentioned that I probably should have shown some of the more basic functionality of the API. I hope this post will give you a better idea of the possibilities a scripting framework can bring to your applications.

The following is the Micro Effects 5 Minute Tutorial I've scraped from the upcoming Micro Effects website (http://microfx.bericotechnologies.com [Not Available Yet!]). Please let me know if it took you more than 5 minutes to read, or if it sparked any other general questions about the framework.

Richard

Micro Effects in 5 Minutes

In this demonstration, we will instantiate the Engine, add an "ad hoc" script, and then instruct the engine to run.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using com.berico.mfx;

namespace com.berico.mfx.examples {
  
  public class MicroEffects2MinuteExample {

    public static void Main(string[] args) {

      new MfxEngine()
         .Load(
          new Script() { 
            Info = ScriptInfo.Bldr().ID("My Script").Build(),
            Body = "console.log('Hello World.');"
          })
         .Run();
         
      Console.ReadLine();
    }
  }
}

   
By default, the Console logs to the Debug output (System.Diagnositics.Debug). You will not see anything on your console screen. If you look at the Debugger output, you will find the following line intermixed with other debugging information.
2011-04-24T17:38:15.6270000-04:00 [My Script] INFO - Hello World.
We will continue to operate in the Main method of the class, but for the sake of brevity, we will not include the surrounding code.
Let's make this demonstration even smaller by importing the "loaders" namespace, which adds extension methods onto the Micro Effects engine (MfxEngine).
using com.berico.mfx.loaders;

/* ... */

new MfxEngine()
  .Load("console.log('Hello World.');")
  .Run();

   
Once again, in the Debugger output, you should see an identical line (timestamp and script
name being the only things that have changed).

2011-04-24T17:59:02.8810000-04:00 [AdHoc] INFO - Hello World.

Ok, we admit that looking for the output in the Debug window is annoying. In the next example, we will redirect that output to the Console Window.
This brings us to our next concept. The MfxEngine does not exist on it's own, but actually operates within a Micro Effects Environment (MfxEnvironment). MfxEngine and MfxEnvironment are bidirectionally associated (in that they are aware of each other's existence). It's more appropriate to say MfxEngine is an aggregate of MfxEnvironment, in that one environment may have many engines. The environment provides the engine with a number of services, including providing logging support ("console"), global variables, and a service registry.
When you instantiate an engine, the engine is associated with the default environment. If you need to configure the environment, it's best to start by retrieving and configuring the default environment and grabbing an engine from it.

using com.berico.mfx.loaders;
using com.berico.mfx.services;

/* ... */

MfxEnvironment
  .Default
  .RegisterConsole(typeof(WindowsConsoleService))
  .GetEngine()
  .Load("console.log('Hello World.');")
  .Run();

You should now finally see the message in the Console window.




Note, we had to reference the com.berico.mfx.services namespace, where all Console Implementations are stored. Implementing your own IConsoleService is really quite simple. Keep in mind, we already provide implementations that
use the Windows Debugger (DebugConsoleService), Windows Console (WindowsConsoleService) and Log4NET (Log4NetConsoleService).
If you register more than one console service with Environment, the environment will wrap all console services in the CompositeConsoleService, routing the logging output to each registered console sequentially.

Now that you better understand how Micro Effects is instantiate, let us conclude with a couple of "rapid fire" examples of using Micro Effects.

Register a Variable with the Engine.

DateTime now = DateTime.Now;

MfxEnvironment
  .Default
  .RegisterConsole(typeof(WindowsConsoleService))
  .GetEngine()
  .SetVar("currentTime", now)
  .Load(
   "console.log('The current time is {0}.', currentTime.ToString());")
  .Run();


2011-04-24T20:08:53.2340000-04:00 [AdHoc] INFO - The current time is 4/24/2011 8:08:52 PM.

Call a C# function from JavaScript.

public static string StringToLower(string input){
  return input.ToLower();
}

public static void Main(string[] args) {

DateTime now = DateTime.Now;

MfxEnvironment
  .Default
  .RegisterConsole(typeof(WindowsConsoleService))
  .GetEngine()
  .SetFunction("StringToLower", 
     new Func<string, string>(MicroEffects2MinuteExample.StringToLower))
  .Load("console.log('MICRO EFFECTS to lower: {0}.'," 
      + "StringToLower('MICRO EFFECTS'));")
  .Run();

 Console.ReadLine();
}

2011-04-24T20:16:37.9640000-04:00 [AdHoc] INFO - MICRO EFFECTS to lower: micro effects.

Call a JavaScript function from C#.

*Note: the JINT engine uses System.Double as the return type of mathematical
operations in JavaScript, so if you ask for an integer return value, you will get a cast error.

MfxEngine engine = MfxEnvironment.Default
  .RegisterConsole(typeof(WindowsConsoleService))
  .GetEngine()
  .Load("function add(var1, var2){ return var1 + var2; }")
  .Prepare();

double sum = engine.CallFunction<double>("add", 1.1234, 2.1234132);

Console.WriteLine("The sum of 1.1234 and 2.1234132 is {0}.", sum);

The sum of 1.1234 and 2.1234132 is 3.2468132.

Load a Script from the File System.

C:\Scripts\test.mfx.js
console.error("Ooops!");
console.fatal("Huge error");
console.log("New Console Message");

function iterate(){
  for(var i = 0; i < 10; i++){
    console.log("Iteration {0}", i);
  }
}

iterate();

var anonObj = {
  name: "Anonymous object"
};

console.log("Name: {0}", anonObj.name);

(function(){ console.log("Anonymous function called."); })();

Load the file by submitting a FileInfo object to the Load function (extension method).

MfxEnvironment.Default
  .RegisterConsole(typeof(WindowsConsoleService))
  .GetEngine()
  .Load(new FileInfo("C:\\Scripts\\test.mfx.js"))
  .Run();

2011-04-24T20:47:54.7370000-04:00 [C:\Scripts\test.mfx.js] ERROR - Ooops!
2011-04-24T20:47:54.7620000-04:00 [C:\Scripts\test.mfx.js] FATAL - Huge error
2011-04-24T20:47:54.7650000-04:00 [C:\Scripts\test.mfx.js] INFO - New Console Message
2011-04-24T20:47:54.7810000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 0
2011-04-24T20:47:54.7900000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 1
2011-04-24T20:47:54.7920000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 2
2011-04-24T20:47:54.7930000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 3
2011-04-24T20:47:54.7940000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 4
2011-04-24T20:47:54.7950000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 5
2011-04-24T20:47:54.7960000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 6
2011-04-24T20:47:54.7980000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 7
2011-04-24T20:47:54.7990000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 8
2011-04-24T20:47:54.8000000-04:00 [C:\Scripts\test.mfx.js] INFO - Iteration 9
2011-04-24T20:47:54.8040000-04:00 [C:\Scripts\test.mfx.js] INFO - Name: Anonymous object
2011-04-24T20:47:54.8050000-04:00 [C:\Scripts\test.mfx.js] INFO - Anonymous function called.

Load a Script from a Website.

http://microfx.bericotechnologies.com/content/fivemindemo/external.js
console.log("Hello from the WWW!");

Load the file by submitting an Uri object to the Load function (extension method).

MfxEnvironment.Default
  .RegisterConsole(typeof(WindowsConsoleService))
  .GetEngine()
  .Load(new Uri(
"http://microfx.bericotechnologies.com/content/fivemindemo/external.js"))
  .Run();

2011-04-24T20:54:38.9880000-04:00 [/content/fivemindemo/external.js] INFO - Hello from the WWW!

You have survived the Micro Effects 5 Minute Demo, and hopefully it only took you 5 minutes!
Micro Effects has much more to offer, and we you walk away with a sense of the possibilities
a Scripting framework can bring to your architecture.

Last updated: April 24, 2011 @ 9:00pm.