.在.NET中使用DLR(转载)

转载自:http://chen1996.blog.163.com/blog/static/4441005220091117102310427/

前言

    看到许多朋友写过,在C#中调用DLR脚本的方法,但没有一个说的完整。如今我要说一个详细完整的,希望能对您有所帮助。本文,主要通过C#与IronPython脚本,来体现.NET与脚本互操作的过程。

什么是DLR

    DLR(Dynamic Language Runtime),是微软主导的一个开源项目。为.NET应用程序,提供了脚本技持。目前版本为0.9,你可以从Codeplex获得源吗。具体可以看我的博文《研究研究DLR》

总览

image1

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

  1. 通过ScriptRuntime.ExcuteFile获得ScriptScope
  2. 通过ScriptRuntime.UseFile获得ScriptScope
  3. 通过ScriptRuntime.CreateScope获得ScriptScope,再执行ScripeScope.Execute或ScripeScope.IncludeFile
  4. 通过ScriptRuntime.GetEngine或ScriptRuntime.GetEngineByFileName获得ScriptEngine。调用ScriptEngine的CreateScriptSourceFromString或CreateScriptSourceFromFile或CreateScriptSourceFromStream创建ScriptSource,再执行ScriptSource.Execute。
  5. 有了ScriptSource也不一定要Execute,可以先调用Compile,产生CompiledCode,最后调用CompiledCode.Execute。

引用DLR

    首先,当然要获得DLR模块对应的DLL。您可以从Codeplex,下载取得。内容如下: 
Image2
我在工程目录下面建了一个DLR目录,并把这些文件都Copy进去。然后在解决方案资源管理器视图中,右键“引用”选择“添加引用” 
Image3 
点击“浏览”如下图 
Image4 
将“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进行初始化。

  1. 首先要使用namespace 
    using Microsoft.Scripting.Hosting;
  2. 接着定义与创建ScriptRuntime 
    ScriptRuntime env = ScriptRuntime.CreateFromConfiguration(); 
    ScriptScope scope;
  3. 加载脚本,我在窗体的构造函数里,加入如下标黄的代码

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方法,调用脚本的函数。这里我介绍委托的方式。

  1. 定义委托 
    delegate void ScriptOnLoad(Window window); 
    委托的参数形式,与脚本的参数一致。
  2. 调用脚本的函数 
    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语言。

转载自:http://chen1996.blog.163.com/blog/static/4441005220091117102310427/

posted @ 2012-11-27 10:50  脸谱匠  阅读(2481)  评论(1编辑  收藏  举报