Question

Je suis en train d'utiliser Groovy pour créer un script interactif / mode macro pour mon application.L'application est OSGi et une grande partie de l'information les scripts peuvent avoir besoin est de ne pas savoir d'avance.J'ai pensé que je pourrais utiliser GroovyShell et appeler la fonction eval() à plusieurs reprises en permanence l'ajout de l'espace de bundles OSGi sont chargés.GroovyShell maintient la variable d'état sur plusieurs eval appels, mais pas les définitions de classes ou de méthodes.

objectif:Créer une classe de base lors du démarrage.Comme les bundles OSGi charge, de créer des classes dérivées en tant que de besoin.

Était-ce utile?

La solution 2

Fini l'injection de code avant chaque script de compilation.L'objectif final est que l'utilisateur écrit le script dispose d'un domaine spécifique de la langue disponible pour utilisation.

Autres conseils

Je ne suis pas sûr de ce que tu veux dire sur les classes déclarées non existant entre est évaluée comme, les deux scripts fonctionnent comme prévu lors de la evaled l'un après l'autre:

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

...

new C()

Cependant ces méthodes ne sont pas liés à la classe qui les a déclarés, et GroovyShell crée une nouvelle classe pour chaque instance.Si vous n'avez pas besoin de la valeur de retour de l'un des scripts et ils sont vraiment scripts (et non des classes avec des méthodes principales) vous pouvez joindre les documents suivants à la fin de chaque évalués scrips.

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

Si l'on dépend de la valeur de retour, vous pouvez à la main la gestion de l'évaluation et exécuter le script dans le cadre de votre analyse (attention, le code non testé suit, par exemple, utilise seulement)...

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

Il y a une dernière mise en garde, je suis sûr que vous êtes conscient de.Typé statiquement les variables ne sont pas conservés entre est évaluée comme comme ils ne sont pas stockées dans la liaison.Ainsi, dans le script précédent, la variable "klass" ne va pas être maintenue entre le script invocations et disparaîtra.Pour remédier à cela tout simplement supprimer le type déclarations lors de la première utilisation de toutes les variables, ce qui signifie qu'elles seront lues et écrites à la liaison.

Cela pourrait être ce que vous recherchez?

À partir de Groovy en 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

Une utilisation appropriée de Liaison va vous permettre de maintenir l'état?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top