22

यदि आप नहीं जानते कि मैं किस बारे में बात कर रहा हूं तो the tutorial पर जाएं और निर्भरता को इंजेक्शन जोड़ने का प्रयास करें या समस्या के बारे में मेरी व्याख्या के साथ अपनी किस्मत आजमाएं।क्या ASP.NET MVC संपर्क प्रबंधक ट्यूटोरियल में निर्भरता इंजेक्शन लूप समस्या को हल करने का कोई अच्छा/उचित तरीका है?

नोट: यह समस्या ASP.NET पर मूल ट्यूटोरियल के दायरे में नहीं है। ट्यूटोरियल केवल सुझाव देता है कि इस्तेमाल किए गए पैटर्न निर्भरता इंजेक्शन अनुकूल हैं।

समस्या मूल रूप से नियंत्रक, मॉडलस्टेटवापर और ContactManagerService के बीच एक निर्भरता पाश है।

  1. संपर्क नियंत्रक कन्स्ट्रक्टर एक आईकॉन्टैक्ट प्रबंधक सेवा लेता है।
  2. ContactManagerService निर्माता एक IContactManagerRepository (महत्वपूर्ण नहीं) और एक IValidationDictionary (जो ModelStateWrapper औजार) लेता है।
  3. मॉडलस्टेटवापर कन्स्ट्रक्टर मॉडलस्टेट डिक्शनरी (जो नियंत्रक पर "मॉडलस्टेट" नामक एक संपत्ति है) लेता है।

तो निर्भरता चक्र की तरह इस चला जाता है: नियंत्रक> सेवा> ModelStateWrapper> नियंत्रक

आप इस के लिए निर्भरता इंजेक्शन जोड़ने का प्रयास करते हैं, तो यह असफल हो जायेगी। तो मेरा सवाल है; मुझे इसके बारे में क्या करना चाहते हैं? अन्य ने इस सवाल को पोस्ट किया है, लेकिन उत्तर कम, अलग हैं, और सभी थोड़े "हैक-आश" लगते हैं। इस संरचना के साथ

public class ContactController : Controller 
{ 
    private readonly IContactService _contactService; 

    public ContactController(IContactService contactService) 
    { 
     _contactService = contactService; 
     contactService.Initialize(new ModelStateWrapper(ModelState)); 
    } 

    //Class implementation... 
} 

public class ContactService : IContactService 
{ 
    private IValidationDictionary _validationDictionary; 
    private readonly IContactRepository _contactRepository; 

    public ContactService(IContactRepository contactRepository) 
    { 
     _contactRepository = contactRepository; 
    } 

    private void Initialize(IValidationDictionary validationDictionary) 
    { 
     if(validationDictionary == null) 
      throw new ArgumentNullException("validationDictionary"); 

     _validationDictionary = validationDictionary; 
    } 

    //Class implementation... 
} 

public class ModelStateWrapper : IValidationDictionary 
{ 
    private readonly ModelStateDictionary _modelState; 

    public ModelStateWrapper(ModelStateDictionary modelState) 
    { 
     _modelState = modelState; 
    } 

    //Class implementation... 
} 

मैं इस तरह मेरी एकता कंटेनर कॉन्फ़िगर कर सकते हैं:

public static void ConfigureUnityContainer() 
{ 
    IUnityContainer container = new UnityContainer(); 

    // Registrations 
    container.RegisterTypeInHttpRequestLifetime<IContactRepository, EntityContactRepository>(); 
    container.RegisterTypeInHttpRequestLifetime<IContactService, ContactService>(); 

    ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container)); 
} 

मेरे वर्तमान समाधान IModelStateWrapper इस तरह के बजाय IService निर्माता से दूर करने के लिए और जोड़ने के लिए कोई Initialize विधि है

दुर्भाग्य से इसका मतलब है कि सेवा पर "आरंभ करें" विधि को नियंत्रक कन्स्ट्रक्टर द्वारा मैन्युअल रूप से कहा जाना चाहिए। क्या कोई बेहतर तरीका है? हो सकता है कि जहां मैं किसी भी तरह से अपनी एकता विन्यास में IValidationDictionary शामिल हो? क्या मुझे एक और डी कंटेनर पर स्विच करना चाहिए? क्या मैं कुछ भूल रहा हूँ?

+0

मैं स्वीकार करने के लिए मैं इस ट्यूटोरियल 3 बार किया है और कभी भी इस पार नहीं आए हैं है? क्या स्रोत में समस्या या मैन्युअल रूप से ट्यूटोरियल का पालन करना है, यदि यह बाद वाला है तो संभवतः एक चरण गुम हो रहा है? – BinaryMisfit

+0

प्रश्न मूल ट्यूटोरियल के दायरे से बाहर चला गया है जो केवल निर्भरता इंजेक्शन पर संकेत देता है लेकिन यह दिखाने के लिए कभी नहीं आया कि यह कैसे किया जाना चाहिए। मैं इस सवाल को स्पष्ट करूंगा। – JohannesH

उत्तर

11

एक सामान्य विचार के रूप में, परिपत्र निर्भरता एक डिजाइन दोष से संकेत मिलता है - मुझे लगता है कि मैं सुरक्षित रूप से यह कह सकता हूँ जब से तुम कोड :)

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

जब तक कि मैं पूरी तरह से गलत नहीं हूं, संपर्क नियंत्रक को इसके क्रिया विधियों को लागू करने से पहले IValidationDictionary उदाहरण की आवश्यकता नहीं है?

यदि यह सच है, तो सबसे आसान समाधान संभवतः एक IValidationDictionaryFactory इंटरफ़ेस को परिभाषित करना होगा और संपर्क नियंत्रक निर्माता इस इंटरफ़ेस का उदाहरण लेंगे।

यह इंटरफ़ेस इस तरह परिभाषित किया जा सकता है:

public interface IValidationDictionaryFactory 
{ 
    IValidationDictionary Create(Controller controller); 
} 

कि एक IValidationDictionary उदाहरण की जरूरत है तो उदाहरण पाने के लिए बनाने के लिए विधि आह्वान कर सकते हैं नियंत्रक पर कोई कार्रवाई विधि।

डिफ़ॉल्ट कार्यान्वयन कुछ इस तरह दिखेगा:

public class DefaultValidationDictionaryFactory : IValidationDictionaryFactory 
{ 
    public IValidationDictionary Create(Controller controller) 
    { 
     return controller.ModelState; 
    } 
} 
+0

अनाम डाउनवोट क्यों? –

+6

मार्क, मैं अज्ञात डाउनवॉटर नहीं हूं लेकिन मेरा मानना ​​है कि यहां समस्या यह है कि कंट्रोलर कैसे प्राप्त करें। मॉडेलस्टेट आईसीओन्टैक्ट सेवा उदाहरण में आबादी के लिए सुंदरता है। आपके समाधान के साथ, यदि IContactService उदाहरण में IValidalidDictionaryFactory उदाहरण प्राप्त करने के लिए थे, तो हमें अभी भी विधि बनाने के लिए, सेवा के भीतर से नियंत्रक के उदाहरण की आवश्यकता होगी। – Ben

+0

संपर्क सेवा में IValidationDictionaryFactory कैसे प्राप्त करें? यह ContactService में होना चाहिए – 1AmirJalali

1

प्रत्येक नियंत्रक एक आभासी विधि प्रारंभ ऐसे ही काम करना है।

मुझे लगता है कि कोई बेहतर तरीका नहीं है क्योंकि IValidalidDictionary आपके वर्तमान अनुरोध/नियंत्रक/मॉडलस्टेट और आईसीओन्टैक्ट सेवा के बीच एक अमूर्त परत है। नियंत्रक इंजेक्शन का उपयोग कर नियंत्रक में सेवा को इंजेक्शन और फिर नियंत्रक में सेवा इंजेक्शन करना असंभव है। पहले होना चाहिए।

संपत्ति इंजेक्शन का उपयोग करने का कोई तरीका हो सकता है? लेकिन मुझे लगता है कि यह भी जटिल होगा।

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