前言 看到许多朋友写过,在C#中调用DLR脚本的方法,但没有一个说的完整。如今我要说一个详细完整的,希望能对您有所帮助。本文,主要通过C#与IronPython脚本,来体现.NET与脚本互操作的过程。 什么是DLR DLR(Dynamic Language Runtime),是微软主导的一个开源项目。为.NET应用程序,提供了脚本技持。目前版本为0.9,你可以从Codeplex获得源吗。具体可以看博文《研究研究DLR》 总览
应用程序执行脚本的方法有很多种: - 通过ScriptRuntime.ExcuteFile获得ScriptScope
- 通过ScriptRuntime.UseFile获得ScriptScope
- 通过ScriptRuntime.CreateScope获得ScriptScope,再执行ScripeScope.Execute或ScripeScope.IncludeFile
- 通过ScriptRuntime.GetEngine或ScriptRuntime.GetEngineByFileName获得ScriptEngine。调用ScriptEngine的CreateScriptSourceFromString或CreateScriptSourceFromFile或CreateScriptSourceFromStream创建ScriptSource,再执行ScriptSource.Execute。
- 有了ScriptSource也不一定要Execute,可以先调用Compile,产生CompiledCode,最后调用CompiledCode.Execute。
引用DLR 首先,当然要获得DLR模块对应的DLL。您可以从Codeplex,下载取得。内容如下:
我在工程目录下面建了一个DLR目录,并把这些文件都Copy进去。然后在解决方案资源管理器视图中,右键“引用”选择“添加引用”
点击“浏览”如下图
将“Microsoft.Scripting.Core.dll”“Microsoft.Scripting.dll”“Microsoft.Scripting.ExtensionAttribute.dll”等文件加入引用。我也不想说的更细了,具体参见Visual Studio的帮助文档。 被引用的文件编译时会自己Copy到Bin目录去的,但没引用的文件是不会Copy的。我的做法是将这些文件加入工程,然后设置Copy。由于我只要使用Python语言,所以我只Copy了“IronPython.dll”、“IronPython.Modules.dll”与“App.Config”几个文件。 初始化 引用了DLR之后,就要对DLR进行初始化。 - 首先要使用namespace
using Microsoft.Scripting.Hosting; - 接着定义与创建ScriptRuntime
ScriptRuntime env = ScriptRuntime.CreateFromConfiguration();
ScriptScope scope; - 加载脚本,我在窗体的构造函数里,加入如下标黄的代码
public Window1()
{
InitializeComponent();
Assembly assembly = Assembly.GetAssembly(typeof(Contact));
env.LoadAssembly(assembly);
scope = env.ExecuteFile("Test.py");
} 前两行代码,执行ScriptRuntime.LoadAssembly,使脚本能直接使用当前程序集中的Class。接下来执行ScriptRuntime.ExecuteFile,运行Test.py脚本。 调用脚本的函数 要调用脚本的函数,首先要定义一个方法的委托。通过委托调用脚本,是最高效的方式。当然,也可以用DynamicObject的TryInvoke方法,调用脚本的函数。这里我介绍委托的方式。 - 定义委托
delegate void ScriptOnLoad(Window window);
委托的参数形式,与脚本的参数一致。 - 调用脚本的函数
ScriptOnLoad fun;
if (scope.TryGetVariable<ScriptOnLoad>("OnLoad", out fun))
fun(this);
以上代码,TryGetVariable根椐函数名,获得委托。然后,再通过委托就可以直接调用脚本了。当然,您也可以将委托存起来,从而高效的调用函数。
脚本调用C#下面看看Test.py脚本。 import WpfApplication
def OnLoad(Window):
dataProvider = Window.FindResource("myDateCollectionDataSource")
data = dataProvider.Data;
c = WpfApplication.Contact("Chen1996", "Chen1996是个聪明人")
data.Add(c)
这个脚本不长,但有三个关键点值得关注。 第一行的import语句,相当于C#的using。其中WpfApplication,是这个C#程序的名字空间。之前初始化时调用LoadAssembly,还记得吗?ScriptRuntime的这个函数,就是用来加载程序集供脚本使用的。 接下来第三行,Window.FindResource,非常简单的调用C#中的方法。DLR提供得,.NET原生支持就是好。后面第四行与第六行也都一样。这里并不依赖,初始化时通过LoadAssembly加载的程序集,因为一切都源参数Window这个对像。 第四行,创建了一个WpfApplication.Contact的对象。WpfApplication,就是之前初始化时加载的程序集。为了要使用这个程序集里的类,就必须先加载。然后,就可以像使用脚本自己的类型一样使用了。还是得益于DLR,为我们提供的.NET原生支持,哈哈。 总之,C#与Python之间互操作,非常的简单又高效。同理通过这个例子,完全可以应用到所有的脚本语言及.NET语言。
|