zoukankan      html  css  js  c++  java
  • .NET 动态脚本语言Script.NET 入门指南 Quick Start

    Script.NET是一种动态的脚本语言,它使得程序可扩展,可定制,和维护性好。和Office系列的VB Script相似,可以在应用中嵌入大量的代码块,以便在运行时才执行这些代码。

    Script.NET的设计理念是:简单(simplicity),有效率(efficiency),容易上手(intuitive)。先通过例子,来做一个基本的了解。

    using System;
    using System.Diagnostics;
    using System.IO;
    using ScriptNET;
    using ScriptNET.Runtime;
    namespace Debug.Net
    {
        class Program
        {
            static void Main(string[] args)
            {
                RuntimeHost.Initialize();
                Script s = Script.Compile("Console.WriteLine('Hello World');");
                s.Execute();
                RuntimeHost.CleanUp();         
            }
        }
    
    }

    为了编译这个例子,请先添加对程序集ScriptDotNet.dll的引用,它的Target是.NET 3.5。这个例子可以看出,Script.NET是如何调用.NET Framework的类型,并调用它的方法。再来看一个例子

    RuntimeHost.Initialize();
    object obj=Script.RunCode(" return 1+1;");
    Console.WriteLine(obj);

    这个例子演示了,如何运行Script.NET的代码片段。

    数据类型,常量,表达式,语句

    作为一门语言,一般会包含语法,数据类型,表达式,语句,这是语言层面的基础内容。来看下面的表格,

    Script.NET支持的数据类型

    image

    常量,boolean类型的常量是true或false, null表示对象为空,字符串用单引号括起来。

    运算符号:+, -, *, / ,%, ! , | , & , != , > , < , is  。其中is用于对象类型。

    请看下面的例子表达式,

    X = (y+4)*2;
    Y = a[5] + 8;
    Z = Math.Sqrt(256);
    P = new System.Drawing.Point(3,4);

    语句 Script.NET程序是语句的集合,有三种常用的语句:顺序(sequencing ),循环(loop),分支(branching)

    If ... Then ... Else ...     if (Expression) statement else Statement

    if (x>0) y = y + 1 ; else y = y ?1;      if (x>0) message = 'X is positive';

    For ...    for (Expression1;Expression2;Expression3) Statement

    sum=0;
    for(i=0; i<10; i++)
       sum = sum + a[i];

    Foreach ... in ...    foreach (Identifier in Expression) Statement

    arr=[1,2,3,4,5];    sum = 0;
    foreach(i in arr ) sum = sum + i;

    While ...   while (Expression) Statement

    while (i>0) i = i-1;

    Switch

    switch (expr){
    case expr1: statement
       ...
    default: statement
    }

    switch (i){
       case 1: MessageBox.Show('Hello!');
       case 2: MessageBox.Show('?');
       default: MessageBox.Show('No way');
    }

    Break, Continue   只用于循环语句中,用于跳出循环
    Return  用于返回函数(function)

    函数 function

    Script.NET是脚本语言,而不是面向对象的OOP语言。通常会将一将代码片段封装成函数,函数的定义语法如下

    function(id1,id2,…,idn) {

    statement} 

    function fac(n){

      if (n==1) return 1;

      else return n*fac(n-1);

    }

    MessageBox.Show(fac(5).ToString());

    Func_pointer = fac;

    Func_pointer(4);


    下面的代码,演示了Script.NET与Host的交互,从Host中获取值

    RuntimeHost.Initialize();         
    List<int> vals = new List<int>();
    vals.AddRange(new int[] { 1, 2, 3, 4 });
    Script script = Script.Compile(@"
             rez = 0;
             foreach (number in numbers)
             rez += number;"
              );
    
    script.Context.SetItem("numbers", vals);
    object rez = script.Execute();
    Console.WriteLine(rez); 

    运行程序,输出结果如下

    image

    Script Context  脚本上下文

    脚本上下文存储运行时信息,变量,和引入的类型,它可以引入.NET的对象到脚本中,以运用.NET Framework的强大功能。下面的例子演示Script.NET与Host的类型互操作

    class Program
        {
            static void Main(string[] args)
            {
                RuntimeHost.Initialize();
                Type type = RuntimeHost.GetType("A");
                object script = Script.RunCode(@" a=new A();
                              a.Name='From Script.NET';
                               return a.Name;
                               ");
                Console.WriteLine(script);
            }
        }
        public class A
        {
            public string Name { get; set; }
        }

    在Host中定义类型A,并引用它,可以在Script.NET中直接使用。也可在Host中定义类型,然后把它的值传到Script.NET中,请看例子

    RuntimeHost.Initialize();
    Type type = RuntimeHost.GetType("A");
    A a = new A();
    a.Name = "From Host";
    Script script = Script.Compile(@"
                     ab.Name='From Script.NET';
                      return ab.Name;
                       ");
    script.Context.SetItem("ab", a);
    script.Execute();
    Console.WriteLine(script);

    启动调试,在script.Execute执行前后,对象a的Name属性值是不同的。

     

    Runtime Configuration 运行时配置

    在Script.NET压缩包的根目录,找到配置文件RuntimeConfig.xml,把它添加到项目中。它包含,要引用的程序集,类型映射,和运行Script.NET引擎时,可以指定的初试化代码。

    <References>
       <Assembly name="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" sn="true"/>
    </References>
    <Types>
       <Type alias="string" name="System.String" />
       <Type alias="int" name="System.Int32" />

       ……

    </Types>

    <Initialization>
        <![CDATA[
        ]]>
      </Initialization>

    比如,可以在Initialization区域定义数值常量,或是初始化代码,如下所示

    <Initialization>
        <![CDATA[
           Pi=3.14;
           Console.WriteLine('Jack is right');
        ]]>
      </Initialization>

    再回到Script.NET脚本代码中,代码如下

    RuntimeHost.Initialize(new FileStream("RuntimeConfig.xml",FileMode.Open));
    Script script = Script.Compile(@"
                     Console.WriteLine(Pi);                           
                       ");
    script.Execute();
    Console.WriteLine(script);

    运行程序,可看到控制台输邮结果如下

    image

    注意,Script.NET的标识符是大小写敏感的,如果在脚本调用中把Pi写成了PI,会报异常。

    Unhandled Exception: ScriptNET.Runtime.ScriptIdNotFoundException: Namespace PI is not found

    Script.NET原来的名称是S#, 文档和实际的代码有差异。我是根据对.NET的理解来推断它的用法,发生错误的原因,再加上它本身是个开放源码的项目,可以直接集成到现有的应用程序中,发生错误也可以源代码的方式调试。以这种方式,可以将应用程序代码中,将需要动态编译的代码,转化为Script.NET的脚本,借助于Script.NET的强大功能,增加应用程序的灵活性。

  • 相关阅读:
    团队第二次冲刺第六天
    团队第二次冲刺第五天
    [COCI 2017-2018-1]
    IOI2015day1. boxes
    IOI2015day2. horses
    BZOJ#4898. [Apio2017]商旅
    BZOJ#3267. KC采花
    IOI2016Day2. Messy
    IOI2016Day2. Paint
    BZOJ#1717:[Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组+单调队列)
  • 原文地址:https://www.cnblogs.com/aflyfly/p/4053660.html
Copyright © 2011-2022 走看看