我正在嘗試使用Groovy爲我的應用程序創建交互式腳本/宏模式。應用程序是OSGi,腳本可能需要的大部分信息並不知道。我想我可以使用GroovyShell,並隨着OSGi包的加載,多次調用eval()不斷追加到名稱空間。 GroovyShell通過多個eval調用維護變量狀態,但不支持類定義或方法。我如何說服GroovyShell通過eval()調用維護狀態?
目標:在啓動過程中創建一個基類。當OSGi包加載時,根據需要創建派生類。
我正在嘗試使用Groovy爲我的應用程序創建交互式腳本/宏模式。應用程序是OSGi,腳本可能需要的大部分信息並不知道。我想我可以使用GroovyShell,並隨着OSGi包的加載,多次調用eval()不斷追加到名稱空間。 GroovyShell通過多個eval調用維護變量狀態,但不支持類定義或方法。我如何說服GroovyShell通過eval()調用維護狀態?
目標:在啓動過程中創建一個基類。當OSGi包加載時,根據需要創建派生類。
在每個腳本編譯之前結束注入代碼。最終目標是用戶書面腳本具有可用的特定於域的語言。
這可能是你在找什麼?
def binding = new Binding(x: 6, y: 4)
def shell = new GroovyShell(binding)
def expression = '''f = x * y'''
shell.evaluate(expression)
assert binding.getVariable("f") == 24
適當使用綁定將讓你保持狀態的?
我不知道你的意思evals之間不存在聲明的類的東西,下面的兩個腳本按預期在陸續evaled之一:
class C {{println 'hi'}}
new C()
...
new C()
然而,方法被綁定到聲明它們的類,並且GroovyShell爲每個實例創建一個新類。如果您不需要任何腳本的返回值,並且它們是真正的腳本(不是具有主要方法的類),則可以將以下內容附加到每個評估的腳本的末尾。
Class klass = this.getClass()
this.getMetaClass().getMethods().each {
if (it.declaringClass.cachedClass == klass) {
binding[it.name] = this.&"$it.name"
}
}
如果你依賴於返回值,你可以手工管理的評估和運行腳本作爲分析的一部分(警告,未經測試的代碼如下,僅供說明用途)...
String scriptText = ...
Script script = shell.parse(scriptText)
def returnValue = script.run()
Class klass = script.getClass()
script.getMetaClass().getMethods().each {
if (it.declaringClass.cachedClass == klass) {
shell.context[it.name] = this.&"$it.name"
}
}
// do whatever with returnValue...
我相信你知道最後一個警告。由於靜態類型變量未存儲在綁定中,因此不會保留在evals之間。所以在前面的腳本中,變量'klass'不會保留在腳本調用之間,並且會消失。要糾正這種情況,只需在首次使用所有變量時刪除類型聲明,這意味着它們將被讀取並寫入綁定。
即時消息看着:「f」如何作爲變量進入綁定?即時通訊沒有看到它。 – djangofan 2011-06-18 20:28:12