C#高级编程七十一天----DLR ScriptRuntime

包含DLR ScriptRuntime

DLR是微软的一个开源项目.为.NET影城程序提供了动态脚本注入支持.DLR构建的功能包含两个方面,一个是共享的动态类型系统,一个是标准的承载模型.但是VS并没有继承相关的DLL,大家可以从Codeplex获得源码.这里不得不提及CLR,它是整个运行环境的基础,DLR也是运行在其上,这样是由显而易见的好处的,CLR的垃圾垃圾回收,JIT编译,安全模式,DLR也能享用这些底层架构功能,如果我们对垃圾回收进行优化,或者是提供某种功能,那么DLR相应的也能享用这种便利.DLR内部为了提高执行效率,会让自己先编译脚本,然后缓存.这有些类似JIT机制.避免重复加载,解析外部脚本.

在实际业务逻辑中,我们希望能够实时动态执行存储在文件中的代码或者完整一个业务逻辑功能,甚至我们可以动态选择脚本语言引擎,在应用程序域中动态生成脚本,并注入脚本,来达到控制业务逻辑的目的.

ScriptRuntime: 创建 DLR 运行环境,这是整个执行过程的起始点,它表示一个全局的执行状态(比如程序集引用等等)。每个应用程序域(AppDomain)中可以启动多个 ScriptRuntime。

ScriptScope: 构建一个执行上下文,其中保存了环境及全局变量。宿主(Host)可以通过创建不同的 ScriptScope 来提供多个数据隔离的执行上下文。

ScriptEngine: DLR 动态语言(比如 IronPython) 执行类,可于解析和执行动态语言代码。

ScriptSource: 操控动态语言代码的类型,我们可以编译(Compile)、读取(Read Code Lines)或运行(Execute)代码。

CompiledCode: 调用 ScriptSource.Compile() 将源代码编译成 CompiledCode,这样多次执行就无需重复编译,从而提高执行性能。

ObjectOperations: 提供了相关方法,允许我们在宿主(Host)中操作 DLR 对象成员(Member)。

现在我们来构建脚本引擎

应用程序执行脚本的方法有很多种:

1.通过ScriptRuntime.ExcuteFile获得ScriptScope

2.通过ScriptRuntime.UseFile获得ScriptScope

3.通过ScriptRuntime.CreateScope获得ScriptScope,再执行Script>execute或ScriptScope.IncludeFile

4.通过ScriptRuntime.GetEngine或ScriptRuntime.GetEngineByFileName获得ScriptEngine.调用ScriptEngine的CreateScriptSourceFromStrng或CreateScriptSourceFromFile或CreateScriptSourceFromStream创建ScriptSource,再执行ScriptSource.Execute

5.有了ScriptSource也不一定要Execute,可以先调用Compile,产生CompiledCode,最后调用CompiledCOde.Execute.

说了这么多,你肯定觉得每个例子,说个JB,说不定又觉得我在忽悠你,我是那样的人吗?

下面看看JB,不对,是案例:

第一步,安装:我是用的是VS2012,我从http://ironpython.codeplex.com/releases/view/12482下载的是IronPython-2.6.msi(不大,7M作用),直接安装就可以了.使用默认的安装路径就可以了,C:\Program Files(86)\IronPython 2.6(这是我的默认路径)

第二步:引入相应的dll

看到引用了吗?右键单击,选择添加引用,将C:\Program Files(86)\IronPython 2.6的IronPython.dll,Microsoft.Scripting.Core.dll,Microsoft.Scripting.dll三个dll引入进来.

第三步:应用

C:\Program Files\IronPython 2.6\Tutorial\Tutorial.htm是IronPython的应用指导,写的很仔细。ipy.exe是IronPython 的运行控制台,如果你想学习IronPython 的语法可以使用这个工具。IronPython 的语法这里就不详细介绍了,如果想进一步学习,可以下载IronPython in Action。

看代码:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection;

using System.Text;

using System.Threading.Tasks;

//下面这二个命名空间必须要引入

using Microsoft.Scripting.Hosting;

using IronPython.Hosting;

namespace ConsoleApplication20

{

class Program

{

static void Main(string[] args)

{

/*因为本人没学过Python,所以不会,但是我学过shell和JS,感觉语法差不多,大同小异*/

ScriptEngine engine = Python.CreateEngine();

ScriptScope scope = engine.CreateScope();

var strExpression = "1+2";

var sourceCode = engine.CreateScriptSourceFromString(strExpression);

var actual = sourceCode.Execute<int>();

Console.WriteLine(actual);

Console.ReadKey();

}

}

}

这段代码是用来计算1+2的结果.

ScriptEngine和ScriptScope是在.net中使用IronPython脚本的两个基础类,ScriptSource是运行IronPython的基础类,这里sourceCode就是一个ScriptSource.

有时我们希望给IronPython代码中传入一个变量值:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection;

using System.Text;

using System.Threading.Tasks;

//下面这二个命名空间必须要引入

using Microsoft.Scripting.Hosting;

using IronPython.Hosting;

namespace ConsoleApplication20

{

class Program

{

static void Main(string[] args)

{

ScriptEngine engine = Python.CreateEngine();

ScriptScope scope = engine.CreateScope();

var strExpression = "\"hello:\" + str ";

var sourceCode = engine.CreateScriptSourceFromString(strExpression);

scope.SetVariable("str","python");

var actual=sourceCode.Execute<string>(scope);

scope.RemoveVariable("str");

Console.WriteLine(actual);

Console.ReadKey();

}

}

}

C#调用IronPython函数

ScriptEngine engine = Python.CreateEngine();

ScriptScope scope = engine.CreateScope();

var strExpression = @"def MyFunction(n):return 2*n ";

var sourceCode = engine.CreateScriptSourceFromString(strExpression).Compile().Execute(scope);

var func = engine.GetVariable<Func<int, int>>(scope, "MyFunction");

Console.WriteLine(func(3));

Console.ReadKey();

这里需要注意def MyFunction(n):前面不能有空格,return 2*n必须有空格

IronPython调用C#函数

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection;

using System.Text;

using System.Threading.Tasks;

//下面这二个命名空间必须要引入

using Microsoft.Scripting.Hosting;

using IronPython.Hosting;

namespace ConsoleApplication20

{

class Program

{

static void Main(string[] args)

{

ScriptEngine engine = Python.CreateEngine();

ScriptScope scope = engine.CreateScope();

var strExpression = "CMethod(‘Python‘)";

var sourceCode = engine.CreateScriptSourceFromString(strExpression);

scope.SetVariable("CMethod", (Func<string, string>)TMethod);

var actual = sourceCode.Execute<string>(scope);

scope.RemoveVariable("CMethod");

Console.WriteLine(actual);

Console.ReadKey();

}

public static string TMethod(string info)

{

return "Hello:" + info;

}

}

}

案例:如果需要使用某个对象中的某个函数

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection;

using System.Text;

using System.Threading.Tasks;

//下面这二个命名空间必须要引入

using Microsoft.Scripting.Hosting;

using IronPython.Hosting;

namespace ConsoleApplication20

{

class Program

{

static void Main(string[] args)

{

ScriptEngine engine = Python.CreateEngine();

ScriptScope scope = engine.CreateScope();

Test test = new Test();

var strExpression = @"test.Hello()

";

var sourceCode = engine.CreateScriptSourceFromString(strExpression);

scope.SetVariable("test", test);

var actual = sourceCode.Execute<string>(scope);

Console.WriteLine(actual);

Console.ReadKey();

}

}

public class Test

{

public void Hello()

{

Console.WriteLine("hello ,world");

}

}

}

案例:如果需要在IronPython实例化使用某个对象,就稍微复杂一点:

using IronPython.Hosting;

using Microsoft.Scripting.Hosting;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace IronPythonTest

{

class Program

{

static void Main(string[] args)

{

ScriptEngine engine = Python.CreateEngine();

ScriptScope scope = engine.CreateScope();

var strExpression = @"

import clr, sys

clr.AddReference(‘IronPythonTest‘)

from IronPythonTest import *

test=Test()

test.Hello()

";

var sourceCode = engine.CreateScriptSourceFromString(strExpression);

var actual = sourceCode.Execute<string>(scope);

Console.WriteLine(actual);

Console.ReadKey();

}

}

public class Test

{

public string Hello()

{

return "Hello World";

}

}

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-07 16:14:43

C#高级编程七十一天----DLR ScriptRuntime的相关文章

C++面向对象高级编程(七)point-like classes和function-like classes

技术在于交流.沟通,转载请注明出处并保持作品的完整性. 1.pointer-like class 类设计成指针那样,可以当做指针来用,指针有两个常用操作符(*和->),所以我们必须重载这两个操作 /*简单实现一下智能指针的*与 -> 操作符*/ template <class T> class shared_ptr_test { public: T& operator* () const //重载* { return *px; } T* operator->() co

C#高级编程六十九天----DLR简介

DLR 一.近年来,在TIOBE公司每个月发布的编程语言排行榜中,C#总是能挤进前十名,而在最近十年来,C#总体上呈现上升的趋势.C#能取得这样的成绩,有很多因素,其中它在语言特性上的锐意进取让人印象深刻. C#4动态功能是Dynamic Language Runtime(动态语言运行时,DLR)的一部分.DLR是添加到CLR的一系列服务,它允许添加动态语言,如Ruby和Python,并使C#具备和这些动态语言相同的某些功能. 动态编程语言并非什么新鲜事物,早在面向对象编程语言成为主流之前,人们

【读书笔记】C#高级编程 第二十一章 任务、线程和同步

(一)概述 所有需要等待的操作,例如,因为文件.数据库或网络访问都需要一定的时间,此时就可以启动一个新的线程,同时完成其他任务. 线程是程序中独立的指令流. (二)Paraller类 Paraller类是对线程的一个很好的抽象,该类位于System.Threading.Tasks名称空间中,提供了数据和任务并行性. Paraller.For()和Paraller.ForEach()方法在每次迭代中调用相同的代码,二Parallel.Invoke()方法允许同时调用不同的方法.Paraller.I

C#高级编程八十一天----捕获异常

捕获异常 前面主要说了关于异常的一些基础和理论知识,没有进入到正真的异常案例,这一讲通过几个案例来描述一下异常的捕获和处理. 案例代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 异常处理 { class Program { int result; Program() { result =

C#高级编程七十五天----C#使用指针

在C#中使用指针的语法 假设想在C#中使用指针,首先对项目进行过配置: 看到属性了吗?单击: 看到那个同意不安全代码了吗?选中 然后将有关指针,地址的操作放在unsafe语句块中.使用unsafekeyword是告诉编译器这里的代码是不安全的. unsafekeyword的使用: (1)放在函数前,修饰函数,说明在函数内部或函数的形參涉及到指针操作: unsafe static void FastCopy(byte[] src, byte[] dst, int count) { // Unsaf

C#高级编程七十二天----DynamicObject和ExpandoObject

DynamicObject和ExpandoObject 1.ExpandoObject表示一个对象,该对象包含可在运行时动态添加和移除的成员.这个类和动态类型有关,这个类能做些什么? 案例: //ExpandoObject这个类需要引入System.Dynamic; dynamic dynEO = new ExpandoObject(); dynEO.number = 20; dynEO.Method = new Func<int, string>((int i) => { return

C#高级编程七十天----dynamic类型

dynamic类型 C#新增了dynamic关键字,正是因为这一个小小的关键字,C#像前迈进了一大步. dynamic是一个类型关键,声明为dynamic的类型与"静态类型"(这里的静态是指编译时确定的类型,例如int,double类型)相比最大的特定它是"动态类型",它会在运行时尝试调用方法,这些方法的存在与否不是编译时期检查的,而是在运行时查找,如果方法存在并且参数正确,会正确调用,否则会抛出异常. 案例: dynamic d = Console.Out; dy

Unix环境高级编程(七)fork函数总结

在Unix/Linux中用fork函数创建一个新的进程.进程是由当前已有进程调用fork函数创建,分叉的进程叫子进程,创建者叫父进程.该函数的特点是调用一次,返回两次,一次是在父进程,一次是在子进程.两次返回的区别是子进程的返回值为0,父进程的返回值是新子进程的ID.子进程与父进程继续并发运行.如果父进程继续创建更多的子进程,子进程之间是兄弟关系,同样子进程也可以创建自己的子进程,这样可以建立起定义关系的进程之间的一种层次关系. 程序包含位于内存的多个组成部分,执行程序的过程将根据需要来访问这些

(十一) 一起学 Unix 环境高级编程 (APUE) 之 高级 IO

. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录 (四) 一起学 Unix 环境高级编程 (APUE) 之 系统数据文件和信息 (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境 (六) 一起学 Unix 环境高级编程 (APUE) 之 进程控制 (七) 一起学 Unix 环境高级编程 (APUE)