groovy - 如何从 methodMissing、Groovy 元编程中获取被调用者闭包的名称
问题描述
我正在尝试使用 Groovy 的Meta Programming,从闭包中动态读取数据。下面是示例:
class MyClass {
static def metadata1 = {
metadataA(key1: 'value1', key2: "value2")
metadataB(key1: ['value1', 'value2'], key2: 78978)
}
static def metadata2 = {
metadataA(key1: 'value11', key2: "value21")
metadataB(key1: ['value11', 'value21'], key2: 78958)
}
static void main(def args) {
new MyClass().setup("metadata1")
new MyClass().setup("metadata2")
}
def setup(fieldName) {
try {
Field metaField = this.class.getDeclaredField(fieldName)
if (metaField != null) {
metaField.setAccessible(true)
def metaFieldVal = metaField.get(null)
if (metaFieldVal != null) {
metaFieldVal.delegate = this
metaFieldVal() // It will call closure metadata1 or metadata2
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace()
}
}
def methodMissing(String key, args) {
println(key) // metadataA
println(args) // [[key1:value1, key2:value2]]
//println(getNameofCalleeClosure()) //metadata1
}
}
在覆盖的 methodMissing 中,我无法识别被调用者闭包的字段名称,以防万一,即 metadata1、metadata2。Groovy 中是否有任何方法可以从调用位置获取被调用者闭包名称以进行识别?
解决方案
没有像调用者闭包的名称这样的东西。在您的示例中,在方法中setup(fieldName)
搜索存储为类字段的闭包,当您找到闭包时,您使用metaFieldVal()
. metadata1
字段名称和执行为 的闭包之间没有联系metaFieldVal()
。实际上这setup(fieldName)
知道这个闭包被存储为一个类字段,但是闭包本身并不知道它。
如果你想在里面获取metadata1
或metadata2
字段名称,methodMissing()
你必须简单地将它作为这个不存在的方法参数传递。像这样的东西:
class MyClass {
static def metadata1 = {
metadataA("metadata1", [key1: 'value1', key2: "value2"])
metadataB("metadata1", [key1: ['value1', 'value2'], key2: 78978])
}
static def metadata2 = {
metadataA("metadata2", [key1: 'value11', key2: "value21"])
metadataB("metadata2", [key1: ['value11', 'value21'], key2: 78958])
}
static void main(def args) {
new MyClass().setup("metadata1")
new MyClass().setup("metadata2")
}
def setup(fieldName) {
try {
Field metaField = this.class.getDeclaredField(fieldName)
if (metaField != null) {
metaField.setAccessible(true)
def metaFieldVal = metaField.get(null)
if (metaFieldVal != null) {
metaFieldVal.delegate = this
metaFieldVal() // It will call closure metadata1 or metadata2
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace()
}
}
def methodMissing(String key, args) {
println(key) // metadataA
println(args) // [metadata1, [key1:value1, key2:value2]]
}
}
还值得一提的是,像这样执行缺失的方法:
static def metadata1 = {
metadataA(this, [key1: 'value1', key2: "value2"])
metadataB(this, [key1: ['value1', 'value2'], key2: 78978])
}
产生:
[class MyClass, [key1:value1, key2:value2]]
并传递这样的字段metadata1
:
static def metadata1 = {
metadataA(metadata1, [key1: 'value1', key2: "value2"])
metadataB(metadata1, [key1: ['value1', 'value2'], key2: 78978])
}
将产生:
[MyClass$__clinit__closure1@50d0686, [key1:value1, key2:value2]]
因为闭包没有名字。
推荐阅读
- python - 转换为 Python 的异步调用
- reactjs - 从共享同一父域的多个 Web 应用程序注销
- android - 在 RecyclerView 上使用 Glide 缩小图像质量低
- javascript - 这个 Postman Pre-request Script 是如何翻译成 JavaScript 的?
- javascript - 如何从事件监听器的回调函数中返回一个值
- android - 反应原生图像裁剪
- r - 我需要在一组列中找到最大值,然后将每个单独的记录除以该值。有什么帮助吗?使用聚合?
- mysql - 根据每个员工每周/每月的工作天数计算积分
- reactjs - React Context 和 Storybook:在组件故事中更改 React Context 的值
- google-sheets - 为什么在条件格式公式中引用另一个 Google 表格选项卡不起作用?