2009-05-18 17 views
5

Poniższy przykład użycia metody sendMail dostarczonej przez wtyczkę grails pojawia się w this book.Parametry groovy zamknięcia

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

Rozumiem, że kod w {} jest zamknięciem przekazanym do sendmaila jako parametrem. Rozumiem również, że to, subject i body są wywołania metod.

Próbuję dowiedzieć się, co kod, który implementuje metodę Sendmail będzie wyglądać, a mój najlepszy przypuszczenie jest coś takiego:

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 
    } 
} 

Czy to rozsądne, albo ja czegoś brakuje? W szczególności, czy metody przywoływane w zamknięciu (to, subject, body), muszą być członkami tej samej klasy co sendMail?

Dzięki Don

Odpowiedz

1

Nie jestem pewien, co dokładnie robi metoda Sendmail jak nie mam książkę można wymienić. Metoda sendMail rzeczywiście przyjmuje zamknięcie podczas opisywania, ale prawdopodobnie używa raczej builder niż wykonywania w normalny sposób. Zasadniczo byłby to język specyficzny dla domeny do opisu wysyłanej wiadomości e-mail.

Powód, dla którego zdefiniowana przez ciebie klasa nie zadziałał, polega na tym, że zakres zamknięcia jest taki, że nie jest zadeklarowany, gdzie jest uruchamiany. Więc mając zamknięcie wywołaj metodę to(), nie będzie mógł wywołać metody to w MailService, dopóki nie przekażesz instancji usługi pocztowej do zamknięcia.

Po wprowadzeniu kilku zmian Twój przykład może zadziałać, ale będzie używany z regularnym zamknięciem. Następujące zmiany do rozmowy i

// 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()] 
} 

Sposób Sendmail w klasie powinna wyglądać następująco

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

MailService.sendMail zamknięcia delegujący:

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 
} 

i na przykład, metoda do MailMessageBuilder:

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