2008-09-05 91 views
3

我正在嘗試使用Groovy爲我的應用程序創建交互式腳本/宏模式。應用程序是OSGi,腳本可能需要的大部分信息並不知道。我想我可以使用GroovyShell,並隨着OSGi包的加載,多次調用eval()不斷追加到名稱空間。 GroovyShell通過多個eval調用維護變量狀態,但不支持類定義或方法。我如何說服GroovyShell通過eval()調用維護狀態?

目標:在啓動過程中創建一個基類。當OSGi包加載時,根據需要創建派生類。

回答

1

在每個腳本編譯之前結束注入代碼。最終目標是用戶書面腳本具有可用的特定於域的語言。

0

這可能是你在找什麼?

Groovy in Action

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 

適當使用綁定將讓你保持狀態的?

+0

即時消息看着:「f」如何作爲變量進入綁定?即時通訊沒有看到它。 – djangofan 2011-06-18 20:28:12

2

我不知道你的意思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'不會保留在腳本調用之間,並且會消失。要糾正這種情況,只需在首次使用所有變量時刪除類型聲明,這意味着它們將被讀取並寫入綁定。