Как получить имя замыкания вызываемого абонента из метода Missing, Groovy Meta Programming - PullRequest
0 голосов
/ 15 октября 2018

Я пытаюсь использовать 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
    }
} 

В переопределенном методе Missing я не могу определить имя поля закрытия вызываемого абонента, в данном случае, например, metadata1, metadata2.Есть ли какой-нибудь способ в Groovy получить имя закрытия вызываемого абонента для идентификации из того места, где оно называется?

1 Ответ

0 голосов
/ 15 октября 2018

Не существует такого понятия, как имя вызывающего абонента.В вашем примере в методе 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]]

, потому что у замыкания нет имени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...