2009-05-18 10 views
5

El siguiente ejemplo del uso del método sendMail proporcionado por el plugin Grails electrónico aparece en this book.cierre maravilloso Parámetros

sendMail { 
    to "[email protected]" 
    subject "Registration Complete" 
    body view:"/foo/bar", model:[user:new User()] 
} 

entiendo que el código dentro de {} es un cierre que se pasa a Sendmail como un parámetro. También entiendo que to, subject y body son llamadas a métodos.

Estoy tratando de averiguar cuál es el código que implementa el método sendMail se vería así, y mi mejor conjetura es algo como esto:

MailService { 

    String subject 
    String recipient 
    String view 
    def model 

    sendMail(closure) { 
     closure.call() 
     // Code to send the mail now that all the 
     // various properties have been set 
    } 

    to(recipient) { 
     this.recipient = recipient 
    } 

    subject(subject) { 
     this.subject = subject; 
    } 

    body(view, model) { 
     this.view = view 
     this.model = model 
    } 
} 

¿Es esto razonable, o me estoy perdiendo algo? En particular, son los métodos invokedwithin el cierre (to, subject, body), necesariamente miembros de la misma clase que sendMail?

Gracias, Don

Respuesta

1

no estoy seguro exactamente lo que el método de Sendmail como no tengo el libro que mencionas. El método sendMail realmente cierra como se describe, pero probablemente utiliza un builder en lugar de ejecutarse de la forma habitual. Básicamente, ese sería un lenguaje específico del dominio para describir un correo electrónico que se enviará.

La razón por la clase que ha definido no funcionaría es que el alcance de la clausura es donde se declara no donde se ejecuta. Por lo tanto, al hacer que su cierre llame al método to(), no podrá llamar al método to en MailService a menos que pase la instancia del servicio de correo al cierre.

Con algunas modificaciones, el ejemplo podría funcionar, aunque el uso de un cierre regular. Los siguientes cambios en la llamada y

// The it-> can be omitted but I put it in here so you can see the parameter 
service.sendMail {it-> 
    it.to "[email protected]" 
    it.subject "Registration Complete" 
    it.body view:"/foo/bar", model:[user:new User()] 
} 

El método sendMail en la clase debe tener este aspecto

def sendMail(closure) { 
    closure(this) 
    // Code to send the mail now that all the 
    // various properties have been set 
} 
7

MailService.sendMail cierre de delegación:

MailMessage sendMail(Closure callable) { 
    def messageBuilder = new MailMessageBuilder(this, mailSender) 
    callable.delegate = messageBuilder 
    callable.resolveStrategy = Closure.DELEGATE_FIRST 
    callable.call() 

    def message = messageBuilder.createMessage() 
    initMessage(message) 
    sendMail message 
    return message 
} 

y, por ejemplo, el método a por lo MailMessageBuilder:

void to(recip) { 
    if(recip) { 
     if (ConfigurationHolder.config.grails.mail.overrideAddress) 
      recip = ConfigurationHolder.config.grails.mail.overrideAddress 
     getMessage().setTo([recip.toString()] as String[]) 
    } 
} 
Cuestiones relacionadas