2008-09-05 9 views
3

Uygulamam için etkileşimli bir komut dosyası/makro modu oluşturmak için Groovy'yi kullanmaya çalışıyorum. Uygulama OSGi ve komut dosyalarının ihtiyaç duyabileceği bilgilerin çoğu ön tarafa kadar bilinmemektedir. GroovyShell'i kullanabileceğimi düşündüm ve OSGi demetleri yüklendikçe ad alanına sürekli olarak birden fazla kez katılarak eval() öğesini çağırdım. GroovyShell, çoklu durum çağrıları üzerinden değişken durumları korur, ancak sınıf tanımları veya yöntemleri değil.GroovyShell'i durum değerlendirmesi() çağrılarını sürdürmeye nasıl ikna edebilirim?

Hedef: Başlangıç ​​sırasında bir temel sınıf oluşturun. OSGi paketleri yüklendikçe, gerektiğinde türetilmiş sınıflar oluşturun.

cevap

1

Her bir komut derlemesinden önce, enjeksiyon kodunu sonlandırıldı. Son hedef, kullanıcı tarafından yazılan komut dosyasının, kullanıma açık bir alana özgü dile sahip olmasıdır.

0

Bu sizin aradığınız şey olabilir mi? 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 

Eğer durumunu korumak sağlayacak Bağlama Uygun bir kullanım itibaren

? birbiri ardına evaled zaman

+0

şuna bakıyorum: "f" nasıl bir değişken olarak bağlanma içine girer? görmüyorum – djangofan

2

Ben beklendiği gibi aşağıdaki iki komut işe sen evals arasındaki mevcut değil bildirilen sınıflarda hakkında ne anlama konusunda emin değilim:

class C {{println 'hi'}} 
new C() 

...

new C() 

Ancak, yöntemler bunları bildiren sınıfa bağlanır ve GroovyShell her örnek için yeni bir sınıf oluşturur. Eğer betiklerin herhangi birinin geri dönüş değerine ihtiyaç duymuyorsanız ve bunlar gerçekten betikler (ana yöntemlerle sınıflar değil) ise, değerlendirilen her scriptin sonuna aşağıdakileri ekleyebilirsiniz. Eğer değerlendirmeyi el yönetmek ve ayrıştırma bir parçası olarak komut çalıştırabilirsiniz dönüş değeri dayanıyorsa

Class klass = this.getClass() 
this.getMetaClass().getMethods().each { 
    if (it.declaringClass.cachedClass == klass) { 
    binding[it.name] = this.&"$it.name" 
    } 
} 

(uyarı, denenmemiş kodu yalnızca açıklayıcı kullanımlar için aşağıdaki) ...

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... 

Son bir ihtar aldığına eminim. Statik olarak yazılan değişkenler, bağlanmada saklanmadıkları için değerlendirmeler arasında tutulmaz. Bu yüzden önceki betikte 'klass' değişkeni senaryolar arasında saklanmayacak ve kaybolacak. Bunu düzeltmek için, tüm değişkenlerin ilk kullanımındaki tip bildirimlerini kaldırmanız, yani okunacak ve ciltlenmeye yazılacaklardır.

İlgili konular