更新
我要为混淆读者而道歉。在我完全迷失在代码中之后,我从Mercurial repo中恢复了所有更改,仔细应用了与以前相同的逻辑 - 并且它有效。下面的答案帮助我更好地理解(对我来说是新的)概念,为此我给了他们赞成票。
底线:如果在闭包内发生对缺失方法的调用,并且将分辨率设置为DELEGATE_FIRST,则将在委托上调用methodMissing()。如果没有 - 检查你自己的代码,那么在某处就会出现错字。
非常感谢!
答案 0 :(得分: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()并且它有效。
我也不完全理解这个问题,你为什么不能访问闭包的代表呢?您正在设置闭包的委托并将调用闭包,这意味着您将可以访问闭包本身内的委托(并且可以只委托.foo())
答案 1 :(得分:1)
nope,你不会捕获一个丢失的方法并将其重定向到具有元类魔法的委托
封闭代表是 抓住这些调用并将其调整到支持域的机会
这意味着......
您应该使用dsl所需的方法创建自己的委托
如果不是为任务设计的话,不要试图强迫某个类进行委托工作,否则代码会在非时间内变得非常混乱。
在一组专门设计的委托类中保留所有与dsl相关的内容,一切都会突然变得荒谬简单明了。