Domanda

Sto cercando di utilizzare Groovy per creare una modalità scripting/macro interattiva per la mia applicazione.L'applicazione è OSGi e molte delle informazioni di cui potrebbero aver bisogno gli script non sono note in anticipo.Ho pensato che avrei potuto usare GroovyShell e chiamare eval() più volte aggiungendo continuamente allo spazio dei nomi mentre venivano caricati i bundle OSGi.GroovyShell mantiene lo stato variabile su più chiamate eval, ma non definizioni o metodi di classe.

obiettivo:Crea una classe base durante l'avvio.Man mano che i bundle OSGi vengono caricati, crea classi derivate secondo necessità.

È stato utile?

Soluzione 2

Ho finito per iniettare il codice prima di ogni compilazione dello script.L'obiettivo finale è che lo script scritto dall'utente abbia una lingua specifica del dominio disponibile per l'uso.

Altri suggerimenti

Non sono sicuro di cosa intendi con le classi dichiarate che non esistono tra le valutazioni, i seguenti due script funzionano come previsto quando vengono valutati uno dopo l'altro:

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

...

new C()

Tuttavia i metodi vengono vincolati alla classe che li ha dichiarati e GroovyShell crea una nuova classe per ogni istanza.Se non è necessario il valore restituito da nessuno degli script e si tratta di veri script (non classi con metodi principali), è possibile allegare quanto segue alla fine di ogni script valutato.

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

Se dipendi dal valore restituito, puoi gestire manualmente la valutazione ed eseguire lo script come parte dell'analisi (avviso, segue codice non testato, solo per usi illustrativi)...

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

C'è un ultimo avvertimento di cui sono sicuro che tu sia a conoscenza.Le variabili tipizzate staticamente non vengono mantenute tra le valutazioni poiché non vengono archiviate nell'associazione.Quindi nello script precedente la variabile 'klass' non verrà mantenuta tra le invocazioni dello script e scomparirà.Per correggere ciò è sufficiente rimuovere le dichiarazioni di tipo al primo utilizzo di tutte le variabili, ciò significa che verranno lette e scritte nell'associazione.

Potrebbe essere questo quello che stai cercando?

Da Groovy in azione

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

Un uso appropriato del Binding ti consentirà di mantenere lo stato?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top