有趣的Javascript Engine–V8Sharp

有趣的Javascript Engine–V8Sharp

昨天一個朋友介紹我一個新奇有趣又好玩的東西 v8sharp

這是一個javascript的引擎,可以讓我們在本機端或Server端編譯JS

進而可以直接使用JS內的function。

 

整理一下腦袋:

剛接觸時覺得腦袋有些混亂,因為本能覺得Javascript是Client端的語言,

但在使用V8Engine時,都是在本機執行的,所以請想成可以在本機混和

使用Javascript以及C#這兩種語言。

 

使用上很簡單,只要記得幾個步驟:

  1. 取得V8Engine物件
  2. 註冊C#的Class(如果沒有要使用可以不用)
  3. Compile一段Javascript
  4. 執行,取得JS funtion的結果

 

以下程式用 ASP.NET MVC 示範

範例一

public ActionResult Index()
{
    //取得V8Engine
    V8Engine engine = V8Engine.Create();

    //寫一段JS的function,名字叫"Welcome",可以傳一個參數
    V8Script script = engine.Compile(@"function Welcome(name){
                                        return 'Welcome my Blog - '+ name ;
                                       }"
                                     );

    //由於上面的JS只是一個function,如果要使用,必須先執行一次
    engine.Execute(script);

    //這邊就是呼叫上方的JS function "Welcome",並傳入"CodingRoad"這個字串
    object result = engine.Execute("Welcome('CodingRoad')");

    //將結果用ViewData傳到View上
    ViewData["Result"] = result.ToString();

    return View();
}

上面的範例是在c#中呼叫一段簡單的JS function,然後將傳回的字串寫到View上

結果

image

 

範例二

public ActionResult About()
{
    V8Engine engine = V8Engine.Create();

    MyClass my = new MyClass();

    //註冊一個C#的物件,第一個參數名稱可以自己取名,第二個參數是new出的物件
    //共有七種多載可選
    engine.Register("CSharpClass", my);

    //用Execute的另一個多載,直接傳入JS function,
    //並在function中呼叫C#類別MyClass的方法GetChineseDate
    //傳回民國日期
    var result = engine.Execute(@"function ShowDate(){
                        return CSharpClass.GetChineseDate(); //這邊呼叫了自己寫的C#的方法
                    }
                    ShowDate();
                  ");

    ViewData["Date"] = result.ToString();

    return View();
}
public class MyClass
{
    public string GetChineseDate()
    {
        CultureInfo info = new CultureInfo("zh-TW");
        TaiwanCalendar calendar = new TaiwanCalendar();
        info.DateTimeFormat.Calendar = calendar;

        return DateTime.Now.ToString("yyy-MM-dd", info);
    }
}

 

這個範例先註冊了我自己寫的C#的類別,然後再JS中呼叫了GetChineseDate方法

然後執行後將結果傳到View上。

結果

image

 

範例三

 

public ActionResult DiscountPrice()
{
    V8Engine engine = V8Engine.Create();

    //自己寫了一個Extension Method,讀取指定路徑的js
    engine.RegisterFormJsPath(Server.MapPath("~/App_Data/V8UseScript.js"));

    //執行js內的function
    var result=engine.Execute("Discount(3500)");

    ViewData["Price"] = result.ToString();

    return View();
}

Extension Method

 

public static class V8SharpExtension
{
    public static object RegisterFormJsPath(this V8Engine engine, string path)
    {
        string script = File.ReadAllText(path);
        return engine.Execute(script);
    }
}

V8UseScript.js

function Discount(value) {
    var result = parseFloat(value) * 0.8;
    return Math.round(result);
}

這個範例用了我寫的extension method,讀取App_Data內的V8UseScript.js檔

JS內是一個Discount的function,傳入一個參數,打八折後傳回。

結果

image

 

使用上大概是這個樣子

想想我們可以在程式中留一個洞

例如範例三的Discount,然後因應不同的折扣活動,寫不同的JS Function

只要更新JS檔,就可以更改需求,不需要重新編譯。

比起用Reflection抽換dll,或是用Expression寫動態的語法來達成不重新編譯

而更改需求的效果,用JS對大部分的人來說還是比較熟悉的。

而且還可以選擇兩種語法的優點來選擇要用哪種寫,實在是很好玩又方便的東西。

 

範例原始碼下載

 

編譯好的V8Sharp DLL

 

V8Sharp – Codeplex