2013-04-25 10 views
16

मैं कुछ अस्पष्ट जटिल काम को संभालने के लिए एक कस्टम ग्रेडल प्लगइन लिख रहा हूं और प्लगइन लागू होने वाले कुछ कार्यों को कॉन्फ़िगर करने के लिए गुणों का उपयोग करते समय मैंने निराशाजनक समस्या में भाग लिया है।विस्तार को एक संपत्ति के आलसी मूल्यांकन संभाल सकते हैं?

$ gradle thisTaskWorksFine thisTaskWorksIncorrectly 
:thisTaskWorksFine 
You gave me this: Hello 
:thisTaskWorksIncorrectly 
You gave me this: null 

BUILD SUCCESSFUL 

मैं यह बहुत ही अप्रत्याशित रूप में देखते हैं:

apply plugin: myPlugin 

//Provide properties for the applied plugin 
myPluginProps { 
    message = "Hello" 
} 

//Define a task that uses my custom task directly 
task thisTaskWorksFine(type: MyTask) { 
    input = myPluginProps.message 
} 

//Define a plugin that will apply a task of my custom type 
class MyPlugin implements Plugin<Project> { 
    void apply(Project project) { 
     project.extensions.create('myPluginProps', MyPluginExtension) 

     project.task(type: MyTask, 'thisTaskWorksIncorrectly') { 
      input = project.myPluginProps.message 
     } 
    } 
} 

//The extension used by my custom plugin to get input 
class MyPluginExtension { 
    def String message 
} 

//The task used by both the standard build section and the plugin 
class MyTask extends DefaultTask { 
    def String input 

    @TaskAction 
    def action() { 
     println "You gave me this: ${input}" 
    } 
} 

इस फ़ाइल का उपयोग करने से परिणाम इस प्रकार हैं। मेरे दिमाग में, प्लगइन से एक कार्य लागू करना और सीधे लिखना उसी इनपुट को दिया जाना चाहिए जब एक ही इनपुट दिया जाए। इस मामले में, दोनों कार्यों को myPluginProps.message इनपुट के रूप में दिया जाता है, लेकिन प्लगइन द्वारा लागू किया गया कार्य लालची है और शुरुआती शुरुआत में मूल्यांकन करता है। (के दौरान चरण लागू होते हैं?)

एकमात्र समाधान मैं पाया है तो जैसे प्लगइन कार्य के विन्यास ब्लॉक में बंद का उपयोग करने के लिए है:

//Define a plugin that will apply a task of my custom type 
class MyPlugin implements Plugin<Project> { 
    void apply(Project project) { 
     project.extensions.create('myPluginProps', MyPluginExtension) 

     project.task(type: MyTask, 'thisTaskWorksIncorrectly') { 
      input = { project.myPluginProps.message } 
     } 
    } 
} 

कि को छोड़कर बहुत अच्छी तरह से लालची मूल्यांकन समस्या का हल है कि अब कस्टम कार्य को बंद करने के साथ अपेक्षा करने और निपटने के लिए संशोधित किया जाना चाहिए। यह करना मुश्किल नहीं है, लेकिन मुझे नहीं लगता कि यह बंद होने से निपटने के लिए कार्य की ज़िम्मेदारी होनी चाहिए, क्योंकि प्लगइन "दोष देना" है।

क्या मैं यहां गलत तरीके से एक्सटेंशन का उपयोग कर रहा हूं? या वे सिर्फ पर्याप्त नहीं हैं? आधिकारिक रुख यह है कि we should use extensions लेकिन मुझे अभी तक कोई उदाहरण नहीं मिला है जहां एक्सटेंशन की आवश्यकता हो सकती है। मैं बंद होने के उपयोग के साथ आगे बढ़ सकता हूं और बॉयलरप्लेट गेटर्स का एक गुच्छा लिख ​​सकता हूं जो बंद करने के लिए और सामान्य प्रकारों को बंद कर सकते हैं, लेकिन यह ग्रोवी के दर्शन के खिलाफ बहुत ही लगता है और इसलिए धीरे-धीरे बढ़ता है। अगर मैं एक तरीका है कि मैं एक्सटेंशन का उपयोग कर आलसी मूल्यांकन प्राप्त कर सकता हूं तो मैं बहुत खुश हूं।

class MyPlugin implements Plugin<Project> { 
    void apply(Project project) { 
     project.extensions.create('myPluginProps', MyPluginExtension) 

     project.task(type: MyTask, 'thisTaskWorksIncorrectly') { 
      conventionMapping.input = { project.myPluginProps.message } 
     } 
    } 
} 

और उसके बाद कार्य में:

उत्तर

12

इस समस्या के लिए हमेशा की तरह समाधान सम्मेलन मानचित्रण का उपयोग है

class MyTask extends DefaultTask { 
    def String input 

    @TaskAction 
    def action() { 
     println "You gave me this: ${getInput()}" 
    } 

}

कृपया ध्यान दें कि मैं स्पष्ट रूप से के लिए गेटर इस्तेमाल किया input - यदि आप सीधे क्षेत्र का संदर्भ देते हैं तो सम्मेलन मानचित्रण किक नहीं करेगा।

+0

क्या सम्मेलन मानचित्रण और सम्मेलनों के बीच कोई अंतर है? आपका जवाब बहुत हल्का दिखता है, इसलिए मैं लगभग निश्चित रूप से इसका उपयोग करूंगा, लेकिन मूल देवताओं में से एक ने कहा है "संक्षेप में, केवल एक्सटेंशन का उपयोग करें, सम्मेलनों का उपयोग न करें।" शायद मैंने इसे सचमुच ले लिया। –

+2

[सम्मेलन] (http://www.gradle.org/docs/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:convention) जो पीटर उल्लेख कर रहा है पुरानी तंत्र है एक्सटेंशन के लिए। अंतर यह है कि आप एक्सटेंशन के साथ डीएसएल ('myPluginProps {message =" Hello "}') प्राप्त करते हैं और आपको उन्हें सम्मेलनों के साथ नहीं मिला है।सम्मेलन और सम्मेलन मैपिंग दो अलग-अलग चीजें हैं और सम्मेलन मैपिंग का उपयोग आंतरिक रूप से [ग्रेडल कोड] में किया जाता है (https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/groovy/org/gradle/ एपीआई/प्लगइन्स/जावाप्लगिन.जावा # एल 131) बहुत कुछ। – erdi

+0

उत्कृष्ट। मेरे शोध में मैं सम्मेलन शब्द का उल्लेख करने वाली हर चीज को शांत कर रहा था, लेकिन वह जल्दबाजी में था। सलाह के लिए धन्यवाद! –

13

पीटर द्वारा मेरे प्रश्न here में उत्तर इंगित करता है कि सम्मेलन मानचित्रण सुविधा निश्चित रूप से दूर जाएगी। इससे बचने के लिए सबसे अच्छा है।

को हल करने के लिए afterEvaluate का उपयोग करके स्थगित कॉन्फ़िगरेशन समस्या ने मेरा कोड सम्मेलन मैपिंग दृष्टिकोण से बहुत साफ किया है।

class MyPlugin implements Plugin<Project> { 
    void apply(Project project) { 
     project.extensions.create('myPluginProps', MyPluginExtension) 

     project.afterEvaluate { 
      project.task(type: MyTask, 'thisTaskWorksIncorrectly') { 
       input = project.myPluginProps.message 
      } 
     } 
    } 
} 
संबंधित मुद्दे