Pergunta

Estou tentando usar o Groovy para criar um modo de script/macro interativo para meu aplicativo.O aplicativo é OSGi e muitas das informações que os scripts podem precisar não são conhecidas antecipadamente.Achei que poderia usar o GroovyShell e chamar eval() várias vezes, anexando continuamente ao namespace à medida que os pacotes OSGi são carregados.GroovyShell mantém o estado da variável em várias chamadas de avaliação, mas não em definições de classe ou métodos.

meta:Crie uma classe base durante a inicialização.À medida que os pacotes configuráveis ​​OSGi são carregados, crie classes derivadas conforme necessário.

Foi útil?

Solução 2

Acabei injetando código antes de cada compilação de script.O objetivo final é que o script escrito pelo usuário tenha uma linguagem específica do domínio disponível para uso.

Outras dicas

Não tenho certeza do que você quer dizer sobre classes declaradas que não existem entre avaliações. Os dois scripts a seguir funcionam conforme o esperado quando avaliados um após o outro:

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

...

new C()

No entanto, os métodos ficam vinculados à classe que os declarou e GroovyShell cria uma nova classe para cada instância.Se você não precisa do valor de retorno de nenhum dos scripts e eles são realmente scripts (não classes com métodos principais), você pode anexar o seguinte ao final de cada script avaliado.

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

Se você depender do valor de retorno, poderá gerenciar manualmente a avaliação e executar o script como parte de sua análise (aviso, segue código não testado, apenas para usos ilustrativos)...

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

Há uma última advertência que tenho certeza de que você conhece.Variáveis ​​digitadas estaticamente não são mantidas entre avaliações, pois não são armazenadas na ligação.Portanto, no script anterior a variável 'klass' não será mantida entre as invocações do script e desaparecerá.Para corrigir isso basta remover as declarações de tipo no primeiro uso de todas as variáveis, isso significa que elas serão lidas e gravadas na ligação.

Pode ser isso que você está procurando?

De Groovy em ação

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

Um uso apropriado de Binding permitirá manter o estado?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top