2011-10-31 18 views
8

मैं एक सेवा के कई कार्यान्वयन बाध्य करने के लिए चाहते हैं और एक ही बार में कहा जाता है उन सभी को है:Ninject मल्टीकास्टिंग

var kernel = new StandardKernel(); 

kernel.Bind<IBreakfast>.To<Spam>(); 
kernel.Bind<IBreakfast>.To<Eggs>(); 
kernel.Bind<IBreakfast>.To<MoreSpam>(); 

kernel.Get<IBreakfast>().Eat(); // call Eat method on all three bound implementations 

Ninject उस तरह नहीं है, और कई बाइंडिंग होने के बारे में एक अपवाद फेंक देते हैं। क्या कोई तरीका है कि मैं उस त्रुटि के आसपास हो सकता हूं, और सभी कार्यान्वयन कहलाता है?

इसके अलावा, Bind<> कॉल विभिन्न परियोजनाओं में हो सकती है जो रन-टाइम पर लोड हो सकती हैं या नहीं, इसलिए उन्हें कॉल करने के लिए एक ही कार्यान्वयन करना काम नहीं करेगा। यह एएसपी.नेट एमवीसी 3 वेबसाइट के लिए प्लग-इन आर्किटेक्चर का हिस्सा है।

उत्तर

12

यदि आप कंस्ट्रक्टर इंजेक्शन का उपयोग करते हैं और List<IBreakfast> पैरामीटर रखते हैं, तो निनजेक्ट आपके सभी बाइंडिंग का उपयोग करके एक सूची तैयार करेगा। फिर आप इन उदाहरणों पर Eat पर कॉल कर सकते हैं।

उदाहरण के लिए आप अपने प्लगइन की सूची बनाने के लिए निनजेक्ट प्राप्त करने के लिए इस पैटर्न का उपयोग कर सकते हैं।

[Test] 
    public void Test() 
    { 
     IKernel kernel = new StandardKernel(); 

     kernel.Bind<IBreakfast>().To<Eggs>(); 
     kernel.Bind<IBreakfast>().To<Spam>(); 
     kernel.Bind<IBreakfast>().To<MoreSpam>(); 

     var bling = kernel.Get<Bling>(); 
    } 

    private class Bling 
    { 
     public Bling(List<IBreakfast> things) 
     { 
      things.ForEach(t => t.Eat()); 
     } 
    } 

    private interface IBreakfast 
    { 
     void Eat(); 
    } 

    private class Ingrediant : IBreakfast 
    { 
     public void Eat(){Console.WriteLine(GetType().Name);} 
    } 

    private class Eggs : Ingrediant{} 
    private class Spam : Ingrediant{} 
    private class MoreSpam : Ingrediant { } 

आउटपुट:

अंडे
स्पैम
MoreSpam

+0

मैं जब मैं काम करने के लिए मिलता है सुबह में यह कोशिश करता हूँ, लेकिन Ninject 'बाइंड <> (करने के लिए दूसरी कॉल पर एक त्रुटि फेंक नहीं होगा) करें.अभियान <>() '? – MikeWyatt

+5

@ माइकवाइट: नहीं, एकाधिक 'बाइंड ठीक हैं। क्या ठीक नहीं है '' प्राप्त करें जो 'सिंगल 'आइटम से अधिक पैदा करता है। यदि आप ऐसा करना चाहते हैं, तो आप 'GetAll ' का उपयोग कर सकते हैं (या 'सूची ', 'टी []' या 'IEnumerable ' सुझाए गए अनुसार एकाधिक पंजीकरणों के निहित बैचिंग का उपयोग कर सकते हैं) (और जो लोग पोस्ट/कोड करते हैं क्योंकि परीक्षण कभी भी ऐसी चीजें पोस्ट नहीं करते हैं जो उड़ाते हैं!)। ध्यान दें कि निनजेक्ट में आपकी इच्छा के अनुसार कॉल को मल्टीकास्ट करने के लिए एक अंतर्निहित समग्र उत्पन्न करने के लिए कोई अधिकता नहीं है। –

+1

यह बहुत अच्छा काम करता है। धन्यवाद। – MikeWyatt

0

आप कई ठोस वर्ग के लिए एक बार एकल इंटरफेस के लिए बाध्य नहीं कर सकते, कि डि नियमों के खिलाफ है।

मूल रूप से आप क्या करना चाहते हैं, कंक्रीट उदाहरणों को दोबारा शुरू करें और उनकी विधि को कॉल करें।

यह तो आपको देखना चाहेंगे:

Bind<IBreakfast>.To<Spam>().Named("Spam"); 
Bind<IBreakfast>.To<Eggs>().Named("Eggs"); 
Bind<IBreakfast>.To<MoreSpam>().Named("MoreSpam"); 

var breakfastList = new List() { "Spam", "Eggs", "MoreSpam" }; 
breakfastList.ForEach(item => kernel.Get<IBreakfast>(item).Eat()); 
+0

मैं नहीं कहूंगा कि यह डी नियमों के खिलाफ है। यदि आपकी समस्या डोमेन स्वाभाविक रूप से फिट बैठता है तो हमेशा एक इंटरफेस और कंक्रीट कक्षाओं के बीच एक से अधिक रिश्ते होने के नाते, तो यह ठीक है। डीसेंट आईओसी कंटेनर आपको इस परिदृश्य को मॉडल करने देते हैं। ओपी का प्लगइन परिदृश्य इन प्रकार के मॉडल में से एक है। –

+3

यह दृष्टिकोण प्लग-इन आर्किटेक्चर के साथ काम नहीं करता है, क्योंकि परिभाषा के अनुसार, आप नहीं जानते कि कौन से प्लगइन मौजूद होंगे। – Bevan

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