groovy将字符串作为存在于同一脚本中的函数进行求值

groovy将字符串作为存在于同一脚本中的函数进行求值,groovy,eval,evaluate,Groovy,Eval,Evaluate,我试图在groovy中将字符串作为代码进行求值,但由于groovy.lang.MissingMethodExceptionexception而失败,即使方法存在于同一脚本中。据我所知,groovy每次尝试计算代码时都会运行新实例,但是有没有办法将当前脚本注入Eval.me或GroovyShell().evaluate()以便找到方法并运行它? 下面是示例代码片段 def justSayHello(){ return "hello" } def my_str = "justSayHell

我试图在groovy中将字符串作为代码进行求值,但由于
groovy.lang.MissingMethodException
exception而失败,即使方法存在于同一脚本中。据我所知,groovy每次尝试计算代码时都会运行新实例,但是有没有办法将当前脚本注入
Eval.me
GroovyShell().evaluate()
以便找到方法并运行它? 下面是示例代码片段

def justSayHello(){
    return "hello"
}

def my_str = "justSayHello()"
//Eval.me(my_func_str)
new GroovyShell().evaluate(my_func_str) 
Eval
GroovyShell().evaluate()
都抛出下面的异常

Caught: groovy.lang.MissingMethodException: No signature of method: Script1.justSayHello() is applicable for argument types: () values: []
groovy.lang.MissingMethodException: No signature of method: Script1.justSayHello() is applicable for argument types: () values: []
        at Script1.run(Script1.groovy:1)
        at string_split.run(string_split.groovy:35)
以下代码:

justSayHello = {
  println "hello"
}

def my_str = "justSayHello()"

new GroovyShell(binding).evaluate(my_str) 
运行时打印出
hello
。在这里,我们将
justSayHello
从一个方法(在一个隐式类上,您无法看到它,但groovy编译器会围绕您的脚本生成它)更改为一个闭包。此外,我们并不是在做
def justSayHello
,因为这将把它定义为隐式周围类上的一个字段(同样,您看不到,但它在那里),而是在不使用任何修饰符的情况下定义变量,将其放入脚本的全局绑定中

然后我们将绑定发送到GroovyShell,以便它能够找到变量

结果:

─➤ groovy solution.groovy
hello
更通用的变体是执行以下操作:

def justSayHello() {
  println "hello"
}

def someOtherMethod() {
  println "hello again"
}

def methods = this.class.declaredMethods.findResults { m -> 
  if (m.name.startsWith('$') || m.name in ['main', 'run']) return null
  [m.name, this.&"${m.name}"]
}.collectEntries { it }

// just for debugging, print the methods
methods.each { k, v -> 
  println "method: $k"
}

def my_str = "justSayHello()"
new GroovyShell(new Binding(methods)).evaluate(my_str) 
其中打印:

─➤ groovy solution.groovy

method: justSayHello
method: someOtherMethod
hello
在这里,我们在groovy生成的隐式类中找到所有声明的方法,删除groovy编译器添加的一些内容(即
main
run
和以
$
开头的方法),然后将结果映射作为GroovyShell构造函数的绑定发送

我怀疑可能有一种更优雅的方式来实现这一点,所以任何优秀的大师都可以在这里纠正我


有关groovy脚本的隐式封闭类的说明,请参见示例

谢谢@Matias,将方法修改为闭包确实有效,但问题是在我的实时场景中,当前类中没有定义方法,但它是从不同的类导入的。因此,我无法控制修改它,您仍然可以使用第二个方法,并在定义该方法的类中枚举声明的类。除了将
this.class.delclaredMethods
替换为
YourOtherClass.declaredMethods