c# - निर्भरता इंजेक्शन कन्स्ट्रक्टर पागलपन से कैसे बचें?




java dependency-injection (5)

मुझे लगता है कि मेरे रचनाकार इस तरह दिखने लगे हैं:

public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )

हमेशा बढ़ती पैरामीटर सूची के साथ। चूंकि "कंटेनर" मेरा निर्भरता इंजेक्शन कंटेनर है, मैं ऐसा क्यों नहीं कर सकता:

public MyClass(Container con)

हर वर्ग के लिए? डाउनसाइड्स क्या हैं? अगर मैं ऐसा करता हूं, ऐसा लगता है कि मैं एक गौरवशाली स्थिर का उपयोग कर रहा हूं। आईओसी और निर्भरता इंजेक्शन पागलपन पर अपने विचार साझा करें।


आप किस निर्भरता इंजेक्शन ढांचे का उपयोग कर रहे हैं? क्या आपने इसके बजाय सेटर आधारित इंजेक्शन का उपयोग करने की कोशिश की है?

कन्स्ट्रक्टर आधारित इंजेक्शन के लिए लाभ यह है कि यह जावा प्रोग्रामर के लिए प्राकृतिक दिखता है जो डी ढांचे का उपयोग नहीं करते हैं। कक्षा शुरू करने के लिए आपको 5 चीजों की आवश्यकता है तो आपके कन्स्ट्रक्टर के लिए आपके पास 5 तर्क हैं। नकारात्मक बात यह है कि आपने जो देखा है, जब आपके पास बहुत निर्भरताएं होती हैं तो यह अनावश्यक हो जाती है।

वसंत के साथ आप आवश्यक मूल्यों को इसके बजाय सेटर्स के साथ पास कर सकते हैं और आप इनकार किए जाने के लिए @ आवश्यक टिप्पणियां का उपयोग कर सकते हैं। नकारात्मकता यह है कि आपको कन्स्ट्रक्टर से प्रारंभिक कोड को किसी अन्य विधि में स्थानांतरित करने की आवश्यकता है और स्प्रिंग कॉल करें कि सभी निर्भरताओं को @PostConstruct के साथ चिह्नित करके इंजेक्शन दिया जाता है। मैं अन्य ढांचे के बारे में निश्चित नहीं हूं लेकिन मुझे लगता है कि वे कुछ ऐसा ही करते हैं।

दोनों तरीके काम करते हैं, यह वरीयता का मामला है।


आप सही हैं कि यदि आप कंटेनर को सेवा लोकेटर के रूप में उपयोग करते हैं, तो यह एक कम से कम एक स्थिर स्थिर कारखाना है। कई कारणों से मैं इसे एक विरोधी पैटर्न मानता हूं

कन्स्ट्रक्टर इंजेक्शन के अद्भुत लाभों में से एक यह है कि यह एकल जिम्मेदारी सिद्धांत का उल्लंघन स्पष्ट रूप से स्पष्ट करता है।

जब ऐसा होता है, तो यह फेकाडे सेवाओं के लिए रिफैक्टर करने का समय है। संक्षेप में, एक नया, अधिक मोटे अनाज वाले इंटरफ़ेस बनाएं जो वर्तमान में आवश्यक कुछ या सभी अच्छी तरह से जुड़ी निर्भरताओं के बीच बातचीत को छुपाता है।


मुझे नहीं लगता कि आपके वर्ग के रचनाकारों को आपके आईओसी कंटेनर अवधि का संदर्भ होना चाहिए। यह आपकी कक्षा और कंटेनर के बीच एक अनावश्यक निर्भरता का प्रतिनिधित्व करता है (निर्भरता का प्रकार आईओसी से बचने की कोशिश कर रहा है!)।


मैं कन्स्ट्रक्टर आधारित निर्भरता इंजेक्शन और सभी निर्भरताओं में कितना जटिल हो रहा था, के बारे में एक समान प्रश्न में आया।

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

स्पष्टीकरण के साथ विस्तृत कोड यहां पाया जा सकता है

जटिल सेवा परत में आईओसी के लिए सर्वोत्तम अभ्यास


मुसीबत :

1) कभी भी बढ़ती पैरामीटर सूची के साथ निर्माता।

2) यदि वर्ग विरासत में मिला है (पूर्व: RepositoryBase ) तो कन्स्ट्रक्टर हस्ताक्षर बदलने से व्युत्पन्न कक्षाओं में परिवर्तन होता है।

समाधान 1

कन्स्ट्रक्टर को IoC Container पास करें

क्यूं कर

  • कोई और भी बढ़ती पैरामीटर सूची नहीं
  • कन्स्ट्रक्टर का हस्ताक्षर सरल हो जाता है

क्यों नहीं

  • आपको कक्षा को आईओसी कंटेनर के साथ कसकर जोड़ता है। (इससे समस्याएं होती हैं 1. जब आप अन्य वर्गों में उस वर्ग का उपयोग करना चाहते हैं जहां आप विभिन्न आईओसी कंटेनर का उपयोग करते हैं। 2. आप आईओसी कंटेनर को बदलने का फैसला करते हैं)
  • आपको कक्षा कम वर्णनात्मक बनाता है। (आप वास्तव में कक्षा कन्स्ट्रक्टर को नहीं देख सकते हैं और कह सकते हैं कि इसे कार्य करने के लिए क्या चाहिए।)
  • कक्षा संभावित रूप से सभी सेवा तक पहुंच सकती है।

समाधान 2

एक वर्ग बनाएं जो सभी सेवा को समूहित करे और इसे निर्माता को पास करे

 public abstract class EFRepositoryBase 
 {
    public class Dependency
    {
        public DbContext DbContext { get; }
        public IAuditFactory AuditFactory { get; }

         public Dependency(
            DbContext dbContext,
            IAuditFactory auditFactory)
        {
            DbContext = dbContext;
            AuditFactory = auditFactory;
        }
    }

    protected readonly DbContext DbContext;        
    protected readonly IJobariaAuditFactory auditFactory;

    protected EFRepositoryBase(Dependency dependency)
    {
        DbContext = dependency.DbContext;
        auditFactory= dependency.JobariaAuditFactory;
    }
  }

व्युत्पन्न कक्षा

  public class ApplicationEfRepository : EFRepositoryBase      
  {
     public new class Dependency : EFRepositoryBase.Dependency
     {
         public IConcreteDependency ConcreteDependency { get; }

         public Dependency(
            DbContext dbContext,
            IAuditFactory auditFactory,
            IConcreteDependency concreteDependency)
        {
            DbContext = dbContext;
            AuditFactory = auditFactory;
            ConcreteDependency = concreteDependency;
        }
     }

      IConcreteDependency _concreteDependency;

      public ApplicationEfRepository(
          Dependency dependency)
          : base(dependency)
      { 
        _concreteDependency = dependency.ConcreteDependency;
      }
   }

क्यूं कर

  • कक्षा में नई निर्भरता जोड़ना व्युत्पन्न कक्षाओं को प्रभावित नहीं करता है
  • कक्षा आईओसी कंटेनर का अज्ञेयवादी है
  • कक्षा वर्णनात्मक है (इसकी निर्भरताओं के पहलू में)। सम्मेलन से, यदि आप जानना चाहते हैं कि कक्षा A किस निर्भर करता है, तो वह जानकारी AA.Dependency में जमा की A.Dependency
  • कन्स्ट्रक्टर हस्ताक्षर सरल हो जाता है

क्यों नहीं

  • अतिरिक्त कक्षा बनाने की जरूरत है
  • सेवा पंजीकरण जटिल हो जाता है (आपको प्रत्येक X.Dependency अलग से पंजीकृत करने की आवश्यकता है)
  • IoC Container पास करने के रूप में संकल्पनात्मक रूप से
  • ..

समाधान 2 केवल कच्चा है, अगर इसके खिलाफ ठोस तर्क है, तो वर्णनात्मक टिप्पणी की सराहना की जाएगी







ioc-container