Ioc / DI - मुझे आवेदन के प्रवेश बिंदु में सभी परतों / विधानसभाओं का संदर्भ क्यों देना है?


123

(इस प्रश्न से संबंधित, ईएफ 4: आलसी लोडिंग सक्षम होने पर प्रॉक्सी निर्माण को सक्षम क्यों करना पड़ता है? )।

मैं डि के लिए नया हूं, इसलिए मेरे साथ रहिए। मैं समझता हूं कि कंटेनर मेरे सभी पंजीकृत प्रकारों को तुरंत चालू करने का प्रभारी है, लेकिन ऐसा करने के लिए मेरे समाधान में सभी DLL के संदर्भ और उनके संदर्भों की आवश्यकता है।

यदि मैं DI कंटेनर का उपयोग नहीं कर रहा था, तो मुझे अपने MVC3 ऐप में EntityFramework लाइब्रेरी का संदर्भ नहीं देना होगा, केवल मेरी व्यावसायिक परत, जो मेरे DAL / रेपो परत को संदर्भित करेगी।

मुझे पता है कि दिन के अंत में सभी DLL बिन फ़ोल्डर में शामिल होते हैं, लेकिन मेरी समस्या वीएस में "संदर्भ जोड़ें" के माध्यम से स्पष्ट रूप से संदर्भित करने के लिए है ताकि सभी आवश्यक फाइलों के साथ एक WAP प्रकाशित करने में सक्षम हो।


1
.NET में बुक डिपेंडेंसी इंजेक्शन का यह अंश , दूसरा संस्करण मार्क और स्वयं दोनों के उत्तरों का अधिक विस्तृत संस्करण है। इसमें कम्पोज़िट रूट की अवधारणा का विस्तार से वर्णन किया गया है और एप्लिकेशन के स्टार्टअप पथ को हर दूसरे मॉड्यूल पर निर्भर होने देना क्यों वास्तव में एक अच्छी बात है।
स्टीवन

मैं उस अंश लिंक और अध्याय 1 के माध्यम से पढ़ता हूं, मैं पुस्तक खरीद रहा हूं क्योंकि मैंने वास्तव में डीआईजी के जटिल मामले के अनुरूप और सरल स्पष्टीकरण का आनंद लिया है। मुझे लगता है कि आपको एक नया उत्तर सुझाना चाहिए, स्पष्ट रूप से उत्तर देना चाहिए "आपको एंट्री लॉजिकल लेयर में सभी लेयर्स / असेंबलीज़ का संदर्भ देने की ज़रूरत नहीं है, जब तक कि यह आपकी रचना जड़ भी न हो," अंश का लिंक, और चित्र को पोस्ट करें चित्र 3, से अंश।
मृत्युंजय

जवाबों:


194

अगर मैं DI कंटेनर का उपयोग नहीं कर रहा था, तो मुझे अपने MVC3 ऐप में EntityFramework लाइब्रेरी का संदर्भ नहीं देना होगा, केवल मेरी व्यावसायिक परत जो मेरे DAL / रेपो परत को संदर्भित करेगी।

हाँ, यह वही स्थिति है जिससे बचने के लिए DI इतनी मेहनत करता है :)

कसकर युग्मित कोड के साथ, प्रत्येक पुस्तकालय में केवल कुछ संदर्भ हो सकते हैं, लेकिन ये फिर से अन्य संदर्भ हैं, इस तरह निर्भरता का गहरा ग्राफ बनाते हैं:

गहरा ग्राफ

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

हालाँकि, एक शिथिल युग्मित अनुप्रयोग में, कम्पोजीशन रूट के सभी संदर्भों को स्थानांतरित करके , निर्भरता ग्राफ गंभीर रूप से समतल होता है :

उथला ग्राफ

जैसा कि हरे रंग से दर्शाया गया है, अब किसी भी अवांछित निर्भरता के साथ खींचे बिना लाइब्रेरी सी का पुन: उपयोग करना संभव है ।

हालांकि, सभी यह है कि कई डि कंटेनरों के साथ, कहा, तुम नहीं करते है सभी आवश्यक पुस्तकालयों के लिए कठिन संदर्भ जोड़ने के लिए। इसके बजाय, आप कंवेंशन-आधारित असेंबली-स्कैनिंग (पसंदीदा) या XML कॉन्फ़िगरेशन के रूप में देर से बाध्यकारी का उपयोग कर सकते हैं ।

जब आप ऐसा करते हैं, हालाँकि, आपको असेंबली को एप्लिकेशन के बिन फ़ोल्डर में कॉपी करना याद रखना चाहिए, क्योंकि अब यह स्वचालित रूप से नहीं होता है। व्यक्तिगत रूप से, मैं शायद ही कभी इसे अतिरिक्त प्रयास के लायक पाता हूं।

इस उत्तर का अधिक विस्तृत संस्करण मेरी पुस्तक डिपेंडेंसी इंजेक्शन, सिद्धांत, अभ्यास, पैटर्न से इस अंश में पाया जा सकता है ।


3
बहुत बहुत धन्यवाद, यह अब सही समझ में आता है .. मुझे यह जानने की जरूरत है कि क्या यह डिजाइन द्वारा किया गया था। जहाँ तक निर्भरता के सही उपयोग को लागू करने की बात है, मैंने अपने डि बूटस्ट्रैपर के साथ एक अलग परियोजना लागू की थी जैसे स्टीवन ने नीचे उल्लेख किया है जहाँ मैं बाकी पुस्तकालयों का संदर्भ देता हूँ। इस परियोजना को प्रवेश बिंदु ऐप द्वारा संदर्भित किया जाता है और पूर्ण बिल्ड के अंत में, यह बिन फ़ोल्डर में सभी आवश्यक dll का कारण बनता है। धन्यवाद!
डाईगोन्ह

2
@Mark Seemann क्या यह प्रश्न / उत्तर Microsoft के लिए विशिष्ट है? मैं यह जानना चाहूंगा कि क्या सभी निर्भरता को "अनुप्रयोग के प्रवेश बिंदु" पर ले जाने का यह विचार मावेन का उपयोग करके जावा ईई / स्प्रिंग परियोजना के लिए समझ में आता है ... धन्यवाद!
ग्रेजायर सी

5
यह उत्तर .NET से परे लागू होता है। आप रॉबर्ट सी। मार्टिन के पैकेज डिजाइन चैप्टर के सिद्धांतों जैसे कि एगाइल सॉफ्टवेयर डेवलपमेंट, प्रिंसिपल्स, पैटर्न, और प्रैक्टिस
मार्क सेमैन

7
@AndyDangerGagne संरचना रूट एक DI पैटर्न है - सेवा लोकेटर के विपरीत । रचना रूट के दृष्टिकोण से, कोई भी प्रकार बहुरूपी नहीं हैं; रचना रूट सभी प्रकारों को ठोस प्रकारों के रूप में देखता है, और इस प्रकार, Liskov प्रतिस्थापन सिद्धांत उस पर लागू नहीं होता है।
मार्क सेमन

4
एक सामान्य नियम के रूप में, इंटरफेस को क्लाइंट ( एपीपी, ch। 11 ) का उपयोग करके परिभाषित किया जाना चाहिए , इसलिए यदि लाइब्रेरी जे को इंटरफ़ेस की आवश्यकता है, तो इसे लाइब्रेरी जे में परिभाषित किया जाना चाहिए। यह डिपेंडेंसी इनवर्जन प्रिंसिपल का एक कोरोलरी है।
मार्क सीमेन

65

अगर मैं DI कंटेनर का उपयोग नहीं कर रहा था, तो मुझे अपने MVC3 ऐप में EntityFramework लाइब्रेरी का संदर्भ नहीं देना होगा

DI कंटेनर का उपयोग करते समय भी, आपको अपनी MVC3 परियोजना के संदर्भ EF को बताने की आवश्यकता नहीं है, लेकिन आप (संक्षेप में) अपनी MVC3 परियोजना के अंदर कम्पोज़िट रूट (स्टार्टअप पथ जहाँ आप अपनी ऑब्जेक्ट ग्राफ़ बनाते हैं) को लागू करके ऐसा करना चुनते हैं । यदि आप असेंबली का उपयोग करके अपनी स्थापत्य सीमाओं की रक्षा के बारे में बहुत सख्त हैं, तो आप या तो अपनी प्रस्तुति तर्क को एक अलग परियोजना में स्थानांतरित कर सकते हैं।

जब आप स्टार्टअप प्रोजेक्ट से सभी MVC संबंधित लॉजिक (नियंत्रक आदि) को एक क्लास लाइब्रेरी में ले जाते हैं, तो यह इस प्रस्तुति लेयर असेंबली को बाकी एप्लिकेशन से डिस्कनेक्ट रहने की अनुमति देता है। आपका वेब एप्लिकेशन प्रोजेक्ट अपने आप में एक आवश्यक स्टार्टअप तर्क के साथ एक बहुत ही पतला खोल बन जाएगा। वेब एप्लिकेशन प्रोजेक्ट कंपोज़िट रूट होगा जो अन्य सभी विधानसभाओं को संदर्भित करता है।

एमवीसी के साथ काम करने पर एक क्लास लाइब्रेरी में प्रेजेंटेशन लॉजिक को एक्सेप्ट करने से चीजें जटिल हो सकती हैं। सब कुछ तार-तार करना कठिन होगा, क्योंकि नियंत्रक स्टार्टअप परियोजना में नहीं हैं (जबकि दृश्य, चित्र, सीएसएस फाइलें, स्टार्टअप परियोजना में रहने की संभावना है)। यह शायद उल्लेखनीय है लेकिन इसे स्थापित करने में अधिक समय लगेगा।

डाउनसाइड्स की वजह से मैं आमतौर पर वेब प्रोजेक्ट में केवल कंपोजीशन रूट रखने की सलाह देता हूं। कई डेवलपर्स नहीं चाहते हैं कि उनकी MVC विधानसभा DAL असेंबली पर निर्भर हो, लेकिन यह वास्तव में कोई समस्या नहीं है। यह मत भूलो कि असेंबलियाँ एक परिनियोजन कलाकृति हैं; आप कोड को कई विधानसभाओं में विभाजित करते हैं ताकि कोड को अलग से तैनात किया जा सके। दूसरी ओर एक वास्तुशिल्प परत एक तार्किक कलाकृति है। एक ही असेंबली में कई परतें होना बहुत (और आम) संभव है।

इस मामले में हम एक ही वेब एप्लिकेशन प्रोजेक्ट में कंपोज़िट रूट (लेयर) और प्रेजेंटेशन लेयर को समाप्त करेंगे (इस प्रकार एक ही असेंबली में)। और भले ही वह असेंबली DAL युक्त असेंबली का संदर्भ देती है, लेकिन प्रस्तुति परत अभी भी डेटा एक्सेस लेयर का संदर्भ नहीं देती है । यह बड़ा भेद है।

बेशक, जब हम ऐसा करते हैं, हम संकलक के लिए संकलन के समय इस वास्तु नियम की जांच करने की क्षमता खो देते हैं, लेकिन यह एक समस्या नहीं होनी चाहिए। अधिकांश वास्तुशिल्प नियमों को वास्तव में संकलक द्वारा जांचा नहीं जा सकता है और हमेशा सामान्य ज्ञान की तरह कुछ होता है। और अगर आपकी टीम में कोई सामान्य समझ नहीं है, तो आप हमेशा कोड समीक्षाओं का उपयोग कर सकते हैं (जो कि हर टीम को IMO हमेशा btw करना चाहिए)। आप एक उपकरण जैसे ND निर्भर (जो वाणिज्यिक है) का उपयोग कर सकते हैं, जो आपको अपने वास्तु नियमों को सत्यापित करने में मदद करता है। जब आप अपनी निर्माण प्रक्रिया के साथ एनडीटीपी को एकीकृत करते हैं, तो यह आपको चेतावनी दे सकता है जब कोई चेक कोड उस तरह के वास्तु नियम का उल्लंघन करता है।

मेरी पुस्तक डिपेंडेंसी इंजेक्शन, सिद्धांत, अभ्यास, पैटर्न के अध्याय 4 में रचना रूट कैसे काम करता है, इस पर आप अधिक विस्तृत चर्चा पढ़ सकते हैं ।


बूटस्ट्रैपिंग के लिए एक अलग परियोजना मेरा समाधान था क्योंकि हमारे पास कोई निर्भरता नहीं है और मैंने पहले कभी इसका इस्तेमाल नहीं किया है। मैं इसे देखूंगा, क्योंकि यह एक बेहतर तरीका लगता है कि मैं जो करने की कोशिश कर रहा हूं उसे पूरा करने के लिए एक बेहतर तरीका है जब केवल 1 अंतिम आवेदन होगा।
डाइगोब

1
अंतिम पैराग्राफ एक महान है और मुझे अपने दिमाग को बदलने में मदद करने के लिए शुरू हो रहा है कि मैं अलग-अलग विधानसभाओं में परतों को रखने के साथ कितना सख्त हूं। एक असेंबली में दो या अधिक तार्किक परतें होना वास्तव में ठीक है यदि आप कोड के लेखन के आसपास अन्य प्रक्रियाएं (जैसे कोड समीक्षाएं) सुनिश्चित करते हैं कि आपके यूआई कोड और वाइका वर्सा में डीएएल कक्षाओं का कोई संदर्भ नहीं है।
BenM

6

अगर मैं DI कंटेनर का उपयोग नहीं कर रहा था, तो मुझे अपने MVC3 ऐप में EntityFramework लाइब्रेरी का संदर्भ नहीं देना होगा, केवल मेरी व्यावसायिक परत जो मेरे DAL / रेपो परत को संदर्भित करेगी।

आप "डिपेंडेंसीResolver" नामक एक अलग परियोजना बना सकते हैं। इस परियोजना में आपको अपने सभी पुस्तकालयों का संदर्भ देना होगा।

अब यूआई लेयर को संदर्भित नहीं होने के लिए NHibernate / EF या किसी अन्य को UI प्रासंगिक लाइब्रेरी की आवश्यकता नहीं है।

यदि आप अपने UI लेयर से Castle Windsor और DependencyResolver को छुपाना चाहते हैं तो आप एक HttpModule लिख सकते हैं जो IoC रजिस्ट्री सामान कहता है।

मेरे पास केवल StructureMap के लिए एक उदाहरण है:

public class DependencyRegistrarModule : IHttpModule
{
    private static bool _dependenciesRegistered;
    private static readonly object Lock = new object();

    public void Init(HttpApplication context)
    {
        context.BeginRequest += (sender, args) => EnsureDependenciesRegistered();
    }

    public void Dispose() { }

    private static void EnsureDependenciesRegistered()
    {
        if (!_dependenciesRegistered)
        {
            lock (Lock)
            {
                if (!_dependenciesRegistered)
                {
                    ObjectFactory.ResetDefaults();

                    // Register all you dependencies here
                    ObjectFactory.Initialize(x => x.AddRegistry(new DependencyRegistry()));

                    new InitiailizeDefaultFactories().Configure();
                    _dependenciesRegistered = true;
                }
            }
        }
    }
}

public class InitiailizeDefaultFactories
{
    public void Configure()
    {
        StructureMapControllerFactory.GetController = type => ObjectFactory.GetInstance(type);
          ...
    }
 }

DefaultControllerFactory आईओसी कंटेनर का सीधे उपयोग नहीं करता है, लेकिन यह आईओसी कंटेनर विधियों को दर्शाता है।

public class StructureMapControllerFactory : DefaultControllerFactory
{
    public static Func<Type, object> GetController = type =>
    {
        throw new  InvalidOperationException("The dependency callback for the StructureMapControllerFactory is not configured!");
    };

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            return base.GetControllerInstance(requestContext, controllerType);
        }
        return GetController(controllerType) as Controller;
    }
}

GetControllerप्रतिनिधि (विंडसर में यह एक इंस्टालर होना चाहिए) एक StructureMap रजिस्ट्री में सेट है।


1
मुझे यह पसंद है कि मैं क्या कर रहा हूँ की तुलना में बेहतर है, मॉड्यूल महान हैं। तो फिर मैं कंटेनर को कहां करूंगा। मॉड्यूल के भीतर ApplicationEnd या EndRequest घटना ...?
डेन्गोह

1
@Steven क्योंकि Global.asax आपके MVC UI लेयर में है। HttpModule निर्भरताResolver प्रोजेक्ट में होगा।
रूकियन

1
थोड़ा लाभ यह है कि कोई भी UI में IoC कंटेनर का उपयोग नहीं कर सकता है। यानी कोई भी आईओसी कंटेनर को यूआई में सेवा लोकेटर के रूप में उपयोग करने में सक्षम नहीं है।
रूकियन

1
इसके अलावा, यह यूआई परत में डीएएल कोड का उपयोग करके डेवलपर्स को गलती से रोक देता है क्योंकि यूआई में विधानसभा का कोई कठिन संदर्भ नहीं है।
मृत्युंजय

1
मुझे पता चला है कि बूटस्ट्रैपर के जेनेरिक पंजीकरण एपीआई का उपयोग करके समान कार्य कैसे किया जाता है। मेरा UI प्रोजेक्ट बूटस्ट्रैपर, निर्भरता रिज़ॉल्यूशन प्रोजेक्ट का संदर्भ देता है जहां मैं अपने पंजीकरण और मेरे कोर में प्रोजेक्ट (इंटरफेस के लिए) लेकिन मेरे DI फ्रेमवर्क (SimpleInjector) को भी नहीं। मैं बिन फ़ोल्डर में dlls कॉपी करने के लिए OutputTo नगेट का उपयोग कर रहा हूं।
मृत्युंजय

0
  • एक निर्भरता है: यदि एक वस्तु किसी अन्य वस्तु को तुरंत देती है।
  • कोई निर्भरता नहीं है: अगर एक वस्तु एक अमूर्त (contructor इंजेक्शन, विधि इंजेक्शन ...) की उम्मीद करती है
  • असेंबली संदर्भ (संदर्भित dll, webservices ..) निर्भरता अवधारणा से स्वतंत्र हैं, क्योंकि एक अमूर्त को हल करने और कोड को संकलित करने में सक्षम होने के लिए, परत को इसका संदर्भ देना होगा।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.