0

更新

我不得不为让读者感到困惑而道歉。在我完全迷失在代码中之后,我从 Mercurial repo 中恢复了我的所有更改,并小心地应用了与以前相同的逻辑——并且它起作用了。下面的答案帮助我更好地理解(对我来说是新的)概念,为此我给了他们赞成票。

底线:如果在闭包中调用丢失的方法,并且分辨率设置为 DELEGATE_FIRST,则将在委托上调用 methodMissing()。如果不是——检查你自己的代码,某处有错字。

非常感谢!

4

2 回答 2

1

编辑: 好的,现在你已经澄清了你在做什么(有点;--))

另一种方法(我用于 DSL 的方法)是通过 ClosureToMap 实用程序解析您的闭包组以进行映射,如下所示:

// converts given closure to map method => value pairs (1-d, if you need nested, ask)
class ClosureToMap {
    Map map = [:]
    ClosureToMap(Closure c) {
        c.delegate = this
        c.resolveStrategy = Closure.DELEGATE_FIRST
        c.each{"$it"()}
    }
    def methodMissing(String name, args) {
        if(!args.size()) return
        map[name] = args[0]
    }
    def propertyMissing(String name) { name }
}

// Pass your closure to the utility and access the generated map
Map map = new ClosureToMap(your-closure-here)?.map

现在您可以遍历地图,或许可以将方法添加到适用的 MCL 实例。例如,我的一些域具有动态查找器,例如:

def finders = {
    userStatusPaid = { Boolean active = true->
        eq {
            active    "$active"
            paid      true
        }
    }
}

我使用 ClosureToMap 实用程序创建了一个映射,然后进行迭代,将映射键(方法,如“userStatus”)和值(在本例中为闭包“eq”)添加到域实例 MCL,将闭包委托给我们的 ORM,如所以:

def injectFinders(Object instance) {
    if(instance.hasProperty('finders')) {
        Map m = ClosureToMap.new(instance.finders).map
        m?.each{ String method, Closure cl->
            cl.delegate = instance.orm
            cl.resolveStrategy = Closure.DELEGATE_FIRST
            instance.orm.metaClass."$method" = cl
        }
    }
}

通过这种方式在控制器范围内我可以做,说:

def actives = Orders.userStatusPaid()

并且“eq”闭包将委托给 ORM 而不是将发生 MME 的域订单。

玩弄它,希望我已经给你一些关于如何解决问题的想法。在 Groovy 中,如果您不能以一种方式做到这一点,请尝试另一种方式;--)

祝你好运!

原文: 您的 missingMethod 是在字符串元类上定义的;为了调用它,你需要 "someString".foo()

如果您只是在闭包中单独调用 foo() ,则无论使用何种委托策略,它都会失败;即,如果您不使用 (String) 委托,祝您好运。举个例子,做 "".foo() 并且它有效。

我也不完全理解这个问题,为什么你不能访问闭包的代表?您正在设置闭包的委托并将调用闭包,这意味着您将可以访问闭包本身内的委托(并且可以只使用 delegate.foo())

于 2011-05-23T14:36:21.797 回答
1

不,您不会捕获丢失的方法并将其重定向到具有元类魔法的委托。
闭包委托是捕获这些调用并将它们调整到支持域的机会。
这意味着......
您应该使用 dsl 所需的方法创建自己的委托。
如果它不是为任务设计的,不要试图强迫一个类做委托工作,否则代码很快就会变得非常混乱。
将所有与 dsl 相关的东西放在一组专门设计的委托类中,一切都会突然变得非常简单和清晰。

于 2011-05-24T00:42:24.577 回答