開發(fā)的時候,經(jīng)常被策劃頻繁變動的方案而苦惱。這時候就想要加入點動態(tài)語言來輔助一下。
在考慮用動態(tài)語言之前也曾想過使用動態(tài)加載dll的方式,實現(xiàn)基礎(chǔ)接口來調(diào)用。在卸載的時候遇到了問題,雖可以通過應(yīng)用程序域來繞過,但這又加入了應(yīng)用程序域之間的交互。沒有動態(tài)語言來的方便。
IronPython的官網(wǎng):http://ironpython.codeplex.com/
新建一個項目,Consoleapplication
然后NuGet添加IronPython包
在Main函數(shù)中編寫如下代碼:
ScriptEngine engine = Python.CreateEngine(); ScriptScope scope = engine.CreateScope(); string script = "; var sourceCode = engine.CreateScriptSourceFromString(script); var result = sourceCode.Execute<object>(scope); Console.WriteLine(result);
這里用到了三個主要類型:ScriptEngine, ScriptScope, ScriptSource
顧名思義ScriptEngine是引擎,ScriptScope相當(dāng)于一個容器可用于傳遞一些自定義的變量,ScriptSource就是腳本源碼。
運行后輸出結(jié)果:Hello world!
將上面的代碼修改如下
ScriptEngine engine = Python.CreateEngine(); ScriptScope scope = engine.CreateScope(); string script = "print('Hello %d' %number)"; scope.SetVariable("number", 123); ScriptSource sourceCode = engine.CreateScriptSourceFromString(script); var result = sourceCode.Execute<object>(scope); Console.WriteLine(result);
輸出結(jié)果變?yōu)椋篐ello 123
還可以試試更奇妙的,比如C#定義一個類
public class Foo { public string Name { get; set; } public DateTime Birthday { get; set; } }
傳入這個變量試試,修改Main函數(shù)的代碼
ScriptEngine engine = Python.CreateEngine();ScriptScope scope = engine.CreateScope();string script = @"print('Hello %s' %foo.Name)foo.DoSth()";//注意這里換行是必須的Foo foo = new Foo(){ Name = "阿薩德", Birthday = new DateTime(1999,2,2)};scope.SetVariable("foo", foo);ScriptSource sourceCode = engine.CreateScriptSourceFromString(script);var result = sourceCode.Execute<object>(scope);Console.WriteLine(result);
成功輸出:Hello 阿薩德
那么如果調(diào)用Foo里的方法呢?可以哦,你可以試一試,還能夠命中斷點呢!
將script字符串替換為文件路徑,使用ScriptEngine的CreateScriptSourceFromFile方法可以執(zhí)行文件格式的IronPython
新建文件,名為test.py, 將上面的script字符粘貼到文件內(nèi)。修改文件的屬性為“如果較新則復(fù)制”。
那么Main函數(shù)的代碼段就是:
ScriptEngine engine = Python.CreateEngine();ScriptScope scope = engine.CreateScope();string path = @"test.py";Foo foo = new Foo(){ Name = "阿薩德", Birthday = new DateTime(1999,2,2)};scope.SetVariable("foo", foo);ScriptSource sourceCode = engine.CreateScriptSourceFromFile(path);var result = sourceCode.Execute<object>(scope);Console.WriteLine(result);
執(zhí)行成功,輸出結(jié)果不變。
但是此時編輯器對py文件的支持是木有的,此時可以安裝一個插件,Python Tools for Visual Studio 簡稱PTVS,可以在GitHub上獲取到:https://github.com/Microsoft/PTVS/releases
安裝之后,就有了語法高亮和智能提示哦~
這個工具增加了很多對Python的支持,你還能在新建項目中看到新增的Python模板,包括了Django等一些流行的Python網(wǎng)站模板,當(dāng)然IronPython的模板也是不可少的。

還有一個問題,剛才在foo中定義了Birthday這個屬性,但是它的類型是DateTime,如何在IronPython中使用它呢?
修改test.py文件中的代碼
print('Hello %s' %foo.Name)foo.DoSth()from System import DateTimeprint("My birthday is %s" %foo.Birthday.ToString())
這里我使用了from System import DateTime這行語句就引入了DateTime的類型
同樣的,你也可以引入System程序集中的String、TimeSpan等類型,方便得一塌糊涂,比如這樣
from System import *
如果需要添加程序集引用呢?
比如我新建了一個類庫,將Foo類放到了這個新的類庫中,那么我要使用Foo的時候,只要這樣:
import clr,sysclr.AddReference('Foo')from Foo import Foofoo = Foo()foo.Name = "haha"print('Hello %s' %foo.Name)from System import *print("My birthday is %s" %foo.Birthday.ToString())
或許你的程序?qū)⒏嬖V你一個找不到Module的錯誤,那就把Foo.dll拷貝到你的執(zhí)行目錄下。或者你也可以修改Main函數(shù)中的代碼,使用engine.SetSearchPaths(new[]{@"../Foo/bin/Debug"});設(shè)置查找類庫的路徑。
如果報告無法在Foo中找到Foo類型,那就是你拷貝Foo類的代碼到類庫中去的時候沒有使用Foo類庫的namespace。
現(xiàn)在已經(jīng)知道了如何在C#中使用IronPython,以及在IronPython的代碼中使用C#的類型和變量傳遞,那么就可以在你的C#程序中加入炫酷的腳本語言動態(tài)特性了。
關(guān)于CreateScriptSource的時機,你或許可以使用FileSystemWatcher類來監(jiān)視文件修改,不過要注意多線程問題哦。
如果你并不需要在C#中加入IronPython,而僅僅只是想要用Python一樣的語法來做一些.net的程序比如winform、wpf之類的,你可以安裝IronPython的安裝包,安裝包在最上面給出的官網(wǎng)地址中有下載。安裝之后將獲得IronPython單獨運行的環(huán)境和相關(guān)的文檔。


然后你就可以通過PTVS幫你新增的幾個IronPython項目模板來創(chuàng)建你的IronPython程序了。
而且,他們是支持?jǐn)帱c調(diào)試的哦!你是不是有了好點子呢,比如在C#項目中使用Link文件來鏈接IronPython項目中的py文件,^_^
我已經(jīng)迫不及待地想要寫一個可以編輯腳本的小游戲來玩玩了呢。
最后加一個在GitHub上看到的IronPython的小游戲Sample。
新聞熱點
疑難解答