13

में संरचना रूट में डी-कंटेनर उपयोग को ध्यान में रखते हुए यह मुझे स्पष्ट नहीं है कि मैं कैसे डिजाइन कर सकता हूं ताकि मैं सिल्वरलाइट + एमवीवीएम अनुप्रयोग के लिए संरचना रूट में डी-कंटेनर का संदर्भ रखूं।सिल्वरलाइट और एमवीवीएम

मेरे पास निम्न सरल उपयोग परिदृश्य है: एक मुख्य दृश्य (शायद आइटम की एक सूची) और एक ही आइटम के लिए एक संपादन दृश्य खोलने के लिए एक क्रिया है। इसलिए जब मुख्य उपयोगकर्ता कार्रवाई करता है तो संपादन दृश्य को बनाना और दिखाया जाना चाहिए (उदा। कुछ बटन क्लिक करें)।

इसके लिए मैं निम्नलिखित कोड है की तरह तो

public interface ISomeViewFactory 
{ 
    IView CreateView(); 
} 

इस कारखाने है,

public interface IView 
{ 
    IViewModel ViewModel {get; set;} 
} 

फिर, प्रत्येक का मानना ​​है कि मैं बनाने के लिए मैं एक सार कारखाना है सक्षम होना चाहिए के लिए फिर "पेरेंट" व्यू मॉडल की निर्भरता घोषित की गई, जैसे:

public class SomeParentViewModel 
{ 
    public SomeParentViewModel(ISomeViewFactory viewFactory) 
    { 
     // store it 
    } 

    private void OnSomeUserAction() 
    { 
     IView view = viewFactory.CreateView(); 
     dialogService.ShowDialog(view); 
    }  
} 

तो सभी यहां तक ​​ठीक है, कोई DI दृष्टि में कंटेनर :)। अब ISomeViewFactory के कार्यान्वयन आता है:

public class SomeViewFactory : ISomeViewFactory 
{ 
    public IView CreateView() 
    { 
     IView view = new SomeView(); 
     view.ViewModel = ???? 
    } 
} 

"????" भाग मेरी समस्या है, क्योंकि दृश्य के लिए दृश्य मॉडल को डी-कंटेनर से हल करने की आवश्यकता है, इसलिए इसकी निर्भरता इंजेक्शन हो जाती है। मुझे नहीं पता कि मैं संरचना रूट को छोड़कर कहीं भी DI-कंटेनर पर निर्भरता के बिना ऐसा कैसे कर सकता हूं।

एक संभव समाधान है कि या तो कारखाने में इंजेक्ट किया जाता है तो, जैसे दृश्य मॉडल पर निर्भरता के लिए होगा:

public class SomeViewFactory : ISomeViewFactory 
{ 
    public SomeViewFactory(ISomeViewModel viewModel) 
    { 
     // store it 
    } 

    public IView CreateView() 
    { 
     IView view = new SomeView(); 
     view.ViewModel = viewModel; 
    } 
} 

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

एक अन्य समाधान डि-कंटेनर लपेट और कारखानों आवरण पर निर्भर है करने के लिए हो सकता है, लेकिन यह अभी भी वहाँ "भेस में" एक डि-कंटेनर होगा :)

पुनश्च: मेरे वर्तमान समाधान है कि कारखानों को डीआई कंटेनर के बारे में पता है, और यह केवल उन्हें और रचना जड़ है जिस पर यह निर्भरता है।

उत्तर

7

संभव के रूप में अपने उदाहरण कोड के रूप में बने रहने की सुविधा के लिए, आपको IViewPopulator के रूप में अभी तक अविवेक के एक अन्य स्तर पर लागू कर सकते हैं:

public interface IViewPopulator 
{ 
    void Populate(IView view); 
} 

अब आप इस तरह अपने SomeViewFactory लागू कर सकते हैं:

public class SomeViewFactory : ISomeViewFactory 
{ 
    private readonly IViewPopulator populator; 

    public SomeViewFactory(IViewPopulator populator) 
    { 
     if (populator == null) 
     { 
      throw new ArgumentNullException("populator"); 
     } 

     this.populator = populator; 
    } 

    public IView CreateView() 
    { 
     IView view = new SomeView(); 
     this.populator.Populate(view); 
     return view; 
    } 
} 

यह Single Responsibility Principle का पालन करते हुए व्यूमोडल्स की दृश्यों और आबादी के निर्माण को अलग करता है। कुछ हद तक, यह Service Aggregation का एक उदाहरण भी है।

अब आप एक ठोस प्रकार है कि सामान्य निर्भरता लेता है के रूप में IViewPopulator लागू कर सकते हैं:

public class SomeViewPopulator : IViewPopulator 
{ 
    private readonly IDependency dep; 

    public SomeViewPopulator(IDependency dep) 
    { 
     if (dep == null) 
     { 
      throw new ArgumentNullException("dep"); 
     } 

     this.dep = dep; 
    } 

    public void Populate(IView view) 
    { 
     var vm = // Perhaps use this.dep to create an instance of IViewModel... 
     view.ViewModel = vm; 
    } 
} 

वहाँ अन्य तरीकों से आप IVIEW और IViewModel के बीच संबंधों को मॉडल सकता होने की संभावना है, लेकिन इसके बाद के संस्करण एक संभव समाधान का प्रतिनिधित्व करता है।

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

+1

बहुत बहुत धन्यवाद। यद्यपि आपका कार्यान्वयन क्रिस्टल-स्पष्ट है, लेकिन मैंने वास्तव में जो किया वह सिर्फ मेरे कारखानों पर दृश्य मॉडल के लिए निर्भरता घोषित करता था, क्योंकि वे वास्तव में बहुत ही बुनियादी हैं और मुझे लगा कि आपके विचार पॉप्युलेटर की तरह कुछ मेरे लिए अधिक है। फिर भी, एक ठोस दृष्टिकोण से और विशेष रूप से यदि चीजें ज़िम्मेदारी को अलग करने में जटिल होती हैं क्योंकि आपने निश्चित रूप से बहुत कुछ समझ लिया है। ग्रेट सामान :) –

+0

मदद की खुशी है :) –

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