2012-02-07 15 views
8

अतीत में, मैंने swiftsuspenders का उपयोग किया जो एक क्रियालेख 3 आईओसी नियंत्रक है। मूल रूप से स्विट्फसस्पेंडर के पहले संस्करण में निनजेक्ट कर्नेल के समान कुछ था जिसे इंजेक्टर कहा जाता था।मुझे और अधिक निपुण व्यावहारिक उदाहरणों की आवश्यकता है

यदि मैं एक एप्लिकेशन इंजेक्टर बनाना चाहता हूं (चलिए कहते हैं कि आवेदन के दौरान सबसे प्रासंगिक मैपिंग का उपयोग किया जाए), तो मुझे एप्लिकेशन कक्षाओं में इंजेक्टर को इंजेक्ट करना पड़ा।

मुझे आश्चर्य है कि आवेदन में कई कक्षाओं में kernel.get <> का उपयोग करने का अभ्यास क्या है। क्या मुझे कर्नेल को इंजेक्ट करना चाहिए?

व्यक्तिगत रूप से मैं kernel.inject का उपयोग करता हूं लेकिन अगर मैं kernel.inject कर सकता हूं तो मैं वास्तव में निर्भरता को मैन्युअल रूप से इंजेक्ट कर सकता हूं, जो शायद बेहतर (चुंबन) है।

टेस्ट केस अच्छे हैं, लेकिन वे वास्तविक व्यावहारिक मुद्दों से बहुत दूर हैं, इसलिए मुझे आशा है कि आप इस बिंदु को स्पष्ट करने में मेरी सहायता कर सकते हैं। धन्यवाद।

संपादित करें: मैंने देखा है कि कुछ लोग "रूट कंटेनर" के बारे में बात करते हैं, ऐसा लगता है कि यह अवधारणा है जिसे मैं ढूंढ रहा हूं। मुझे रूट कंटेनर कैसे सेट अप करना चाहिए और अन्य एप्लिकेशन क्लास को यह कैसे पता होना चाहिए?

EDIT2 नमूना कोड (कृपया उन त्रुटियों को क्षमा कर, यह सिर्फ उदाहरण के लिए है):

class SomeClass 
{ 
    public SomeClass() 
    { 
     Command cmd = new Command(); 

     cmd.execute(); 
    } 

} 

class SomeOtherClass:ISomeOtherClass 
{ 
public void allright() 
{ 
    //right 
} 
} 

class Command 
{ 
    ISomeOtherClass dependency; 

    void execute() 
    { 
    dependency.allright(); 
    } 

} 


Program.Main() 
{ 
    IKernel kernel = new StandardKernel(); 

    kernel.Bind<SomeClass>().ToSelf().InSingletonScope(); 
    kernel.Bind<ISomeOtherClass>().To<SomeOtherClass>(); 

    SomeClass sc = kernel.Get<SomeClass>(); 
} 

मैं अभी तक यह परीक्षण नहीं किया था, क्योंकि मैं अभी भी कुछ आरंभीकरण मुद्दों के साथ लड़ रहा हूँ, लेकिन मेरे सवाल का, कैसे है क्या कमांड क्लास SomeOtherClass के बारे में जान सकता है? मेरी वर्तमान परिकल्पना कुछ क्लास में कर्नेल को इंजेक्ट करना है और विधि इंजेक्ट का उपयोग करना है।

उत्तर

11

अपना उदाहरण देखकर, यह स्पष्ट है कि SomeClass नियंत्रण में उलटा नियंत्रण के साथ नहीं बनाया गया है; टिप ऑफ यह है कि इसकी Command पर निर्भरता है, लेकिन उस निर्भरता का नियंत्रण SomeClass के अंदर ही बनाए रखा जाता है। (Command cmd = new Command();)

उस निर्भरता के नियंत्रण को नियंत्रित करने के लिए, आपको उस निर्भरता को कुछ क्लास में इंजेक्ट करने का एक तरीका होगा। रेमो ग्लोर has indicated के रूप में, निनजेक्ट के साथ ऐसा करने का मानक तरीका कन्स्ट्रक्टर के माध्यम से है।

ऐसा करने के लिए, आप SomeClass कुछ करने के लिए इस तरह बदल सकता है:

class SomeClass 
{ 
    private ICommand _command; 

    public SomeClass(ICommand injectedCommand) 
    { 
     _command = injectedCommand; 
     _command.execute(); 
    } 

} 

इसी तरह आप अपने आदेश की आवश्यकता होगी अपनी निर्भरता को विज्ञापित करने के:

class Command 
{ 
    private ISomeOtherClass _dependency; 

    public Command(ISomeOtherClass injectedSomeOtherClass) 
    { 
     _dependency = injectedSomeOtherClass; 
    { 

    void execute() 
    { 
     _dependency.allright(); 
    } 
} 

तो फिर आप अपने आदेश में बाध्यकारी रजिस्टर होगा कर्नेल, शायद:

Program.Main() 
{ 
    IKernel kernel = new StandardKernel(); 

    kernel.Bind<SomeClass>().ToSelf().InSingletonScope(); 
    kernel.Bind<ICommand>().To<Command>(); 
    kernel.Bind<ISomeOtherClass>().To<SomeOtherClass>(); 

    SomeClass sc = kernel.Get<SomeClass>(); 
} 

कर्नेल तब टी चलने में सक्षम होगा वह निर्भरता श्रृंखला और उन सभी को इंजेक्ट करें।

+0

उत्तर के लिए धन्यवाद यह समझ में आता है, लेकिन यह सही होने पर, यह केवल यह कहता है कि सभी निर्भरताओं को पहले से जाना जाना चाहिए। क्या होता है जब यह संभव नहीं होता है? (निश्चित रूप से जो मैं कहता हूं वह केवल तभी समझ में आता है जब वस्तुओं को गतिशील रूप से बनाया जा सके) – sebas

+0

मान लें कि कुछ क्लास को गतिशील वस्तुओं की एक निश्चित संख्या बनाना चाहिए। कुछ क्लास की तरह स्तर बन जाते हैं और इसे 30 सितारे बनाना चाहिए। सितारों में कुछ निर्भरताएं होती हैं, कर्नेल का उपयोग करके सितारों पर स्तर उन निर्भरताओं को कैसे इंजेक्ट कर सकता है? – sebas

+0

यह एक अच्छा सवाल है, और आप सरल निर्भरता इंजेक्शन प्रश्नों से आगे बढ़ रहे हैं जिनका उत्तर इस प्रारूप में दिया जा सकता है। इस तरह की स्थिति (जटिल वस्तु निर्माण) को एक और टुकड़ा की आवश्यकता होती है, यही कारण है कि रेमो ने अपने जवाब में कारखानों का उल्लेख किया। आपको या तो स्टार-बिल्डिंग फैक्ट्री बनाने की जांच करनी चाहिए और उसे कुछ क्लास में इंजेक्ट करना चाहिए, या निनजेक्ट को फैक्ट्री विधि या बाइंड() के उपयोग से सितारों को हल करना चाहिए। ToProvider()। –

5

जहां भी संभव हो वहां कन्स्ट्रक्टर इंजेक्शन का उपयोग करें और Factories जब भी कोई अच्छा कारण न हो कि उन पर निर्भर वस्तु के साथ उदाहरण बनाने के लिए कोई अच्छा कारण न हो।

kernel.Inject केवल तभी उपयोग किया जाना चाहिए जब आप ऑब्जेक्ट के निर्माण में बदलाव न करें। जैसे एक वेबफॉर्म

kernel.Get आपके आवेदन को बनाने के लिए अपनी रचना रूट (उदा। प्रोग्राम.माइन या एमवीसी 3. निर्भरता रिसेल्वर) में बिल्कुल एक बार उपयोग किया जाना चाहिए।

+2

हाय रेमो! जवाब के लिए धन्यवाद। आपने उपयोगी जानकारी प्रदान की है, लेकिन यह वह नहीं है जिसे मैं जानना चाहता था। आप मुझे बता रहे हैं कि सेवा लोकेटर के रूप में उपयोग नहीं किया जाना चाहिए, लेकिन मैंने जो पूछा उससे यह अधिक था: मान लीजिए कि मेरे पास एक कक्षा है जिसे अपनी विधि में से एक में कमांड बनाने की आवश्यकता है। आइए मान लें कि कमांड को कुछ निर्भरताओं को इंजेक्शन की आवश्यकता है और कर्नेल को कक्षा के बाहर परिभाषित किया गया है जो कमांड बनाता है। इस आदेश के अंदर निर्भरताओं को इंजेक्ट करने के लिए मुझे कर्नेल का उपयोग कैसे करना चाहिए? क्या मुझे पहले कक्षा में कर्नेल इंजेक्ट करना चाहिए जो कमांड बनाता है? – sebas

+0

मेरी समस्या इस http://stackoverflow.com/questions/2862698/ninject-shared-di-ioc-container के समान कुछ है लेकिन मैं किसी भी स्थिर वर्ग का उपयोग नहीं करता, मैं इस बिंदु पर कर्नेल इंजेक्ट करना पसंद करता हूं। – sebas

+0

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