更新
我不得不为让读者感到困惑而道歉。在我完全迷失在代码中之后,我从 Mercurial repo 中恢复了我的所有更改,并小心地应用了与以前相同的逻辑——并且它起作用了。下面的答案帮助我更好地理解(对我来说是新的)概念,为此我给了他们赞成票。
底线:如果在闭包中调用丢失的方法,并且分辨率设置为 DELEGATE_FIRST,则将在委托上调用 methodMissing()。如果不是——检查你自己的代码,某处有错字。
非常感谢!
更新
我不得不为让读者感到困惑而道歉。在我完全迷失在代码中之后,我从 Mercurial repo 中恢复了我的所有更改,并小心地应用了与以前相同的逻辑——并且它起作用了。下面的答案帮助我更好地理解(对我来说是新的)概念,为此我给了他们赞成票。
底线:如果在闭包中调用丢失的方法,并且分辨率设置为 DELEGATE_FIRST,则将在委托上调用 methodMissing()。如果不是——检查你自己的代码,某处有错字。
非常感谢!
编辑: 好的,现在你已经澄清了你在做什么(有点;--))
另一种方法(我用于 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())
不,您不会捕获丢失的方法并将其重定向到具有元类魔法的委托。
闭包委托是捕获这些调用并将它们调整到支持域的机会。
这意味着......
您应该使用 dsl 所需的方法创建自己的委托。
如果它不是为任务设计的,不要试图强迫一个类做委托工作,否则代码很快就会变得非常混乱。
将所有与 dsl 相关的东西放在一组专门设计的委托类中,一切都会突然变得非常简单和清晰。