8

मैं उपयोगकर्ता इनपुट के आधार पर एकाधिक इंजेक्शन का समर्थन करने के लिए रनटाइम पर गुइस इंजेक्शन को बदलने में सक्षम होना चाहता हूं।रनटाइम पर गिइस बाइंडिंग बदलना

public interface IDao { 
    public int someMethod(); 
} 

public class DaoEarth implements IDao { 
    @Override 
    public int someMethod(){ ... } 
} 

public class DaoMars implements IDao { 
    @Override 
    public int someMethod(){ ... } 
} 

public class MyClass { 
    @Inject 
    private IDao myDao; 

    public int myMethod(String domain) { 
     //If Domain == Earth, myDao should be of the type DaoEarth 

     //If Domain == DaoMars, myDao should be of the type DaoMars 
    } 
} 

मैं अपने खुद के प्रदाता लिखने की सोच रहा था, लेकिन मैं कैसे कि प्रदाता का उपयोग करने के क्रम में मेरी बाइंडिंग बदलने के लिए पता नहीं है: यह मैं प्राप्त करने के लिए चाहते हैं क्या है। किसी भी इनपुट का स्वागत है और सराहना की :) :)

अद्यतन यहाँ मैं वर्तमान के साथ आया है, यह के रूप में सुंदर के रूप में मैं चाहता हूँ नहीं है, तो मैं अभी भी प्रतिक्रिया के लिए देख रहा हूँ

public class DomainProvider { 
    @Inject @Earth 
    private IDaoProvider earthDaoProvider; 

    @Inject @Mars 
    private IDaoProvider marsDaoProvider; 

    public IDaoProvider get(Domain domain){ 
     switch (domain){ 
      case EARTH: 
       return earthDaoProvider; 
      case MARS: 
       return marsDaoProvider; 
     } 
    } 

    public IDaoProvider get(String domain){ 
     Domain parsedDomain = Domain.valueOf(domain.toUpperCase()); 
     return get(parsedDomain); 
    } 
} 

//MarsDaoProvider would be equivalent 
public class EarthDaoProvider implements IDaoProvider { 
    @Inject @Earth 
    private IDao earthDao; 

    public IDao getDao() { 
     return earthDao; 
    } 
} 

This means that in "MyClass", I can do: 
public class MyClass { 
    @Inject 
    private DomainProvider domainProvider; 

    public int myMethod(String domain) { 
     IDaoProvider daoProvider = domainProvider.get(domain); 
     IDao dao = daoProvider.getDao(); 

     //Now "dao" will be of the correct type based on the domain 
    } 
} 

//Of course elsewhere I have the bindings set like 
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class); 
+0

मुझे बिल्कुल यकीन नहीं है कि कैसे इंजेक्शन इंजेक्शन मेरी मदद करेगा। मुझे लगता है कि सहायक इंजेक्शन आपको प्रदान किए गए पैरामीटर के साथ इंजेक्शन पैरामीटर को गठबंधन करने की अनुमति देता है, लेकिन मुझे बिल्कुल यकीन नहीं है कि यह मेरी स्थिति के लिए कैसे काम करेगा। – Nepoxx

उत्तर

12

आपका संस्करण लगभग पूर्ण यह है प्रकार है: आपको किसी प्रकार की ऑब्जेक्ट इंजेक्ट करने की आवश्यकता होगी जो आपके द्वारा लिखे गए कोड के आधार पर एक या दूसरे को लौटाए, और सहायक इंजेक्शन या उसके जैसा कुछ भी नहीं चाहिए। उस ने कहा, आप बॉयलरप्लेट में से कुछ को छोड़ सकते हैं:

public class DomainProvider { 
    // Just inject Providers directly without binding them explicitly. 
    @Inject @Earth Provider<IDao> earthDaoProvider; 
    @Inject @Mars Provider<IDao> marsDaoProvider; 

    public Provider<IDao> get(Domain domain){ 
     switch (domain){ 
      case EARTH: 
       return earthDaoProvider; 
      case MARS: 
       return marsDaoProvider; 
     } 
    } 

    public Provider<IDao> get(String domain){ 
     Domain parsedDomain = Domain.valueOf(domain.toUpperCase()); 
     return get(parsedDomain); 
    } 
} 

उस मामले में आपका MyClass बिल्कुल समान होगा। यहां, Provider या तो एक-विधि जेनेरिक इंटरफ़ेस com.google.inject.Provider है, या इसके समतुल्य निर्मित javax.inject.Provider है जो यह विस्तारित करता है। the relevant Guice wiki topic पर गुइस प्रदाता के बारे में और पढ़ें।

bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class); 
// You can now inject "@Earth IDao" and also "@Earth Provider<IDao>". 
मूल रूप से

, यदि आप कोई अतिरिक्त काम के साथ एक प्रमुख Foo (एक वर्ग, प्रदाता, @Provides विधि, या उदाहरण के लिए), तो आपको automatically get to inject either a Foo or Provider<Foo> बाँध। यह सुनिश्चित करने के लिए प्रदाता भी एक शानदार तरीका है कि आपको get पर प्रत्येक कॉल के साथ एक नया उदाहरण मिल जाए, यदि आप यही चाहते हैं; आपके मूल के साथ, आप हमेशा दिए गए किसी भी डोमेनप्रोवाइडर के लिए धरतीदाओ या मंगलदाओ का एक ही उदाहरण प्राप्त करेंगे। (यदि आपके पास @ सिंगलेटन की तरह बाध्यकारी बाध्यकारी है, तो गुइस भी इसका सम्मान करेगा; प्रदाता केवल साइड पुराने जावा संदर्भ का उपयोग करने के बजाए गुइस को शामिल करने देता है।)

इसका मतलब है कि आप अपने कस्टम EarthDaoProvider और MarsDaoProvider को छोड़ सकते हैं, आपको वास्तव में उन पर कोई बाहरी प्रारंभ करने की आवश्यकता है-जिस बिंदु पर आप शायद bind(EarthDao.class).toProvider(EarthDaoProvider.class) पर कॉल करना बेहतर होगा, इसलिए तैयारी तब भी होती है जब EarthDao को सीधे इंजेक्शन दिया जाता है। आप उचित प्रदाता पर get पर कॉल करके सीधे डोमेनप्रोवाइडर को एक आईडीओ इंस्टेंस वापस कर सकते हैं, और आश्वस्त रहें कि यह हर बार एक नया उदाहरण होगा।

+0

यह एक उत्कृष्ट उत्तर है, स्पष्टीकरण/लिंक के लिए बोनस अंक :) – Nepoxx

+0

"प्रदाता यह सुनिश्चित करने का भी एक शानदार तरीका है कि आपको 'कॉल' करने के लिए प्रत्येक कॉल के साथ एक नया उदाहरण मिलता है - यदि मैं इसके बजाय एक सिंगलटन उदाहरण प्राप्त करना चाहता हूं तो क्या होगा 'कॉल' के लिए हर कॉल के साथ एक नया उदाहरण है? – PapaSierra

+1

@PapaSierra यदि आप इसे Guice में कॉन्फ़िगर करते हैं, तो आपको यही मिल जाएगा; आप इसे गिसिस में वैसे भी कॉन्फ़िगर करना चाहते हैं, इसलिए आपको किसी अन्य उपभोक्ता से अलग उदाहरण नहीं मिल सकता है। मेरा मुद्दा यह है कि एक प्रदाता के बजाय एक उदाहरण को इंजेक्शन करके, आप हमेशा उस इंस्टेंस को वापस कर देंगे, चाहे गुइस में कॉन्फ़िगरेशन के बावजूद। –

संबंधित मुद्दे