8

मैं तर्क को यहां विभिन्न अन्य सवाल पढ़ा है के लिए सही रचना जड़ का पता लगाएँ, सबसे विशेष रूप से एक .NET पुस्तकालय

Dependency Inject (DI) “friendly” library

Ioc/DI - Why do I have to reference all layers/assemblies in entry application?

और इस article (और अन्य विभिन्न सामग्री) ।

हालांकि यह मुझे स्पष्ट नहीं है कि लाइब्रेरी (डीएलएल) .NET प्रोजेक्ट में रचना रूट को कहां रखा जाए। परियोजना लेख में उल्लिखित किसी भी विशिष्ट प्रकार से संबंधित नहीं है। डेस्कटॉप, कंसोल या यहां तक ​​कि वेब एप्लिकेशन में इस बिंदु को स्पष्ट रूप से परिभाषित किया गया है।

मेरे वर्तमान दृष्टिकोण कंटेनर लपेट, रजिस्टर प्रकार और फिर से बेनकाब हल विधि के लिए है:

class DefaultBootstrapper : IBootstrapper { 
    public Bootstrapper() { 
    _container = new XXXContainer(); 
    RegisterTypes(_container); 
    } 

    public T Resolve<T>() where T : class { 
    return _container.Resolve<T>(); 
    } 

    // + other _container.Resolve() overloads 

    private readonly XXXContainer _container; 
} 

तब मैं जड़ उदाहरण बना करने के लिए पुस्तकालय की (जैसे आंतरिक कंस्ट्रक्टर्स परिभाषित) पुस्तकालय उपभोक्ताओं को रोकने के COMPOSITI का पता लगाने के लिए रोजगार की

class XYZFactory { 
    static XYZFactory() {} 

    private XYZFactory(IBootstrapper bootstrapper) { 
    _bootstrapper = bootstrapper; 
    } 

    public static XYZFactory Instance { 
    get { return Singleton; } 
    } 

    public ABCType CreateABCType(string param1) { 
    return _bootstrapper.Resolve<ABCType>(param1, _bootstrapper.Resolve<Dependency1>); 
    } 

    private static readonly XYZFactory Singleton = XYZFactory(new DefaultBootstrapper); 
    private readonly IBootstrapper _bootstrapper; 
} 

सवाल है, वहाँ एक बेहतर तरीका है या एक बेहतर पैटर्न: और इसलिए एक सिंगलटन कारखाने के उपयोग के लिए मजबूर कर रहा लाइब्रेरी प्रोजेक्ट में रूट पर?

उत्तर

13

यह आपके द्वारा बनाई गई लाइब्रेरी के प्रकार पर निर्भर करता है। क्या आपकी लाइब्रेरी प्रोजेक्ट आपके स्वयं के समाधान का हिस्सा है, या यह एक पुन: प्रयोज्य लाइब्रेरी है जो अन्य डेवलपर्स आपकी टीम, विभाग या शायद संगठन के बाहर निर्भर करती है?

यह एक समाधान के पुस्तकालय परियोजना भाग होने के मामले में, लाइब्रेरी प्रोजेक्ट में स्वयं को संरचना रूट नहीं होना चाहिए। परिभाषा के अनुसार, composition root एक अनुप्रयोग में एक "अधिमानतः) अद्वितीय स्थान है जहां मॉड्यूल एक साथ बनाये जाते हैं"। दूसरे शब्दों में, आपके समाधान में एक या एकाधिक स्टार्ट-अप प्रोजेक्ट होंगे (जैसे एमवीसी एप्लीकेशन, डब्ल्यूसीएफ सेवा, कंसोल ऐप), और प्रत्येक स्टार्ट-अप प्रोजेक्ट को अपनी रचना रूट मिल जाएगी। नीचे परतों को अपनी खुद की रचना रूट नहीं मिलेगा।

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

पुन: प्रयोज्य पुस्तकालयों के लिए चीजें आमतौर पर अलग होती हैं। उस स्थिति में उपभोक्ता आपकी लाइब्रेरी का उपयोग करेंगे, लेकिन आपके पास उनके नियंत्रण की संरचना के बारे में कोई नियंत्रण नहीं है। आप अक्सर लाइब्रेरी को इस तरह से आपूर्ति करना चाहते हैं कि उपभोक्ताओं द्वारा इसे सीधे उपभोग किया जा सके, बिना किसी रचनात्मक रूट में सभी प्रकार के 'जटिल' पंजीकरण किए। आप अक्सर यह भी नहीं जानते कि उनके पास संरचना जड़ है या नहीं।

उस स्थिति में आपको आमतौर पर डीआई कंटेनर के बिना अपनी लाइब्रेरी काम करना चाहिए।आपको स्वयं को ऐसे कंटेनर पर निर्भरता नहीं लेनी चाहिए, क्योंकि यह कंटेनर को खींच लेगा। अगर आप कंटेनर का उपयोग करते हैं, तो खुद से सवाल करें कि आपकी पुन: प्रयोज्य लाइब्रेरी कंटेनर का उपयोग क्यों करती है, और यदि यह होना चाहिए। शायद आप ऐसा करते हैं क्योंकि आपने निर्भरता इंजेक्शन सिद्धांत के चारों ओर सभी प्रकारों को डिजाइन किया है; क्योंकि यह परीक्षण को आसान बनाता है। यह न भूलें कि यह आपकी समस्या है, न कि आपके उपभोक्ताओं की समस्या। पुन: प्रयोज्य लाइब्रेरी डिज़ाइनर के रूप में, आपको अपनी लाइब्रेरी को अपने उपभोक्ताओं के लिए यथासंभव उपयोग करने में कठिनाई होनी चाहिए। कृपया कभी नहीं मान लें कि आपके उपभोक्ता एक डी कंटेनर का उपयोग कर रहे हैं। भले ही वे निर्भरता इंजेक्शन का अभ्यास करते हैं, फिर भी वे एक डी कंटेनर के बजाय Pure DI लागू कर सकते हैं।

यदि आप पुन: प्रयोज्य लाइब्रेरी बना रहे हैं, तो मार्क सेमैन से this blog पोस्ट देखें।

+0

मुझे खेद है कि मैं अभी भी वोट नहीं दे सकता (लेकिन मैं 15+ पर होगा)। जब मैं सिर्फ ** ढांचे के परिदृश्य में रूचि रखता था **, जब कंटेनर (यदि मौजूद है) _public इंटरफ़ेस_ से छिपा होगा, तो आपने मुझे कई अलग-अलग प्रस्तुत किए। क्या मैं आपको __poor-man-injection__ के बारे में तर्क (ब्लॉग आलेख या पुस्तक) को गहरा बनाने का संदर्भ कह सकता हूं कि पुन: प्रयोज्य पुस्तकालय उपयोगी होने के मामले में? धन्यवाद, फिर से – jay

+1

मैं अपने तर्कों का बैकअप लेने के लिए किसी भी विशिष्ट कार्य का संदर्भ नहीं दे सकता, लेकिन सामान्य मार्क सीमैन की पुस्तक "डीईटीएंडेंसी इंजेक्शन इन .NET" में DI के बारे में सबसे अच्छा संदर्भ है, हालांकि यह मुख्य रूप से LOB परिदृश्य के बारे में बात करता है। आप स्रोत कोड माइक्रोसॉफ्ट एंटरप्राइज़ लाइब्रेरी देख सकते हैं। ईएल नोट करें एकता पर एक कठोर निर्भरता लेता है, और ऐसा कुछ है जो मुझे लगता है कि आपको पुन: प्रयोज्य लाइब्रेरी लिखते समय रोकने की कोशिश करनी चाहिए। – Steven

+1

यह पुष्टि के रूप में लगता है कि _Dep। इंजेक्शन .NET_ मुझे एक आवश्यक पठन है। मैं इस तर्क में आगे बढ़ जाऊंगा, लेकिन, पुन: प्रयोज्य लाइब्रेरी प्रश्न पर लौटने पर, मुझे लगता है कि ** इस मामले में ** गरीब-इंजेक्शन ** (जैसा कि आप कहते हैं कि यह एक असाधारण है) सही डिजाइन विकल्प है। यह इकाई परीक्षण (** InternalsVisibleTo ** विशेषता के माध्यम से) सक्षम बनाता है और मेरे लिए यह एक केंद्रीय आवश्यकता है। – jay