2010-05-10 5 views
10

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

लक्ष्य व्यूमोडल्स के पदानुक्रम को मॉडल के समान पदानुक्रम में तारित करना है, ताकि प्रत्येक मॉडल में जानकारी पेश करने की ज़िम्मेदारी अपने स्वयं के व्यू मॉडेल कार्यान्वयन के साथ हो। (पैटर्न भी अन्य परिस्थितियों में ऊपर फसलों लेकिन MVVM एक अच्छा उदाहरण के लिए करना चाहिए।)

यहाँ एक सरल उदाहरण है। यह देखते हुए मैं एक मॉडल आगे मॉडल का एक संग्रह है कि है:

public interface IPerson 
{ 
    IEnumerable<IAddress> Addresses { get; } 
} 

public interface IAddress 
{ 
} 

मैं ViewModels में इस पदानुक्रम दर्पण ताकि मैं एक ListBox व्यक्ति ViewModel में एक संग्रह करने के लिए बाध्य (या जो भी) कर सकते हैं करना चाहते हैं:

public interface IPersonViewModel 
{ 
    ObservableCollection<IAddressViewModel> Addresses { get; } 
    void Initialize(); 
} 

public interface IAddressViewModel 
{ 
} 

बच्चे ViewModel बच्चे मॉडल से जानकारी पेश करने के लिए की जरूरत है, तो यह निर्माता के माध्यम से इंजेक्शन है:

public class AddressViewModel : IAddressViewModel 
{ 
    private readonly IAddress _address; 

    public AddressViewModel(IAddress address) 
    { 
     _address = address; 
    } 
} 

सवाल यह है कि, सबसे अच्छा तरीका क्या है संबंधित मॉडल ViewModel को बच्चे मॉडल की आपूर्ति करने के लिए?

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

यहाँ मेरे वर्तमान समाधान है:

माता पिता ViewModel प्रत्येक बच्चे मॉडल के लिए एक बच्चे ViewModel बनाने के लिए की जरूरत है, तो यह एक कारखाने विधि अपने निर्माता को जोड़ा गया है जो इसे प्रारंभ के दौरान का उपयोग करता है:

public class PersonViewModel : IPersonViewModel 
{ 
    private readonly Func<IAddress, IAddressViewModel> _addressViewModelFactory; 
    private readonly IPerson _person; 

    public PersonViewModel(IPerson person, 
          Func<IAddress, IAddressViewModel> addressViewModelFactory) 
    { 
     _addressViewModelFactory = addressViewModelFactory; 
     _person = person; 

     Addresses = new ObservableCollection<IAddressViewModel>(); 
    } 

    public ObservableCollection<IAddressViewModel> Addresses { get; private set; } 

    public void Initialize() 
    { 
     foreach (IAddress address in _person.Addresses) 
      Addresses.Add(_addressViewModelFactory(address)); 
    } 
} 

एक कारखाने विधि है कि Func<IAddress, IAddressViewModel> इंटरफेस को संतुष्ट करता है मुख्य UnityContainer साथ पंजीकृत है। कारखाने विधि IAddress निर्भरता कि ViewModel के लिए आवश्यक है रजिस्टर करने के लिए एक बच्चे के कंटेनर का उपयोग करता है और फिर बच्चे ViewModel का समाधान करता है:

public class Factory 
{ 
    private readonly IUnityContainer _container; 

    public Factory(IUnityContainer container) 
    { 
     _container = container; 
    } 

    public void RegisterStuff() 
    { 
     _container.RegisterInstance<Func<IAddress, IAddressViewModel>>(CreateAddressViewModel); 
    } 

    private IAddressViewModel CreateAddressViewModel(IAddress model) 
    { 
     IUnityContainer childContainer = _container.CreateChildContainer(); 

     childContainer.RegisterInstance(model); 

     return childContainer.Resolve<IAddressViewModel>(); 
    } 
} 

अब, जब PersonViewModel आरंभ नहीं हो जाता है, यह मॉडल और कॉल में प्रत्येक Address के माध्यम से लूप CreateAddressViewModel() (जो Func<IAddress, IAddressViewModel> तर्क के माध्यम से इंजेक्ट किया गया था)। CreateAddressViewModel() एक अस्थायी बच्चे कंटेनर बनाता है और IAddress मॉडल पंजीकृत करता है ताकि जब यह बच्चे कंटेनर से IAddressViewModel निराकरण AddressViewModel सही उदाहरण, अपना निर्माता के माध्यम से इंजेक्शन हो जाता है।

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

  • क्या यह एकता के साथ बच्चे के मॉडल में बच्चे मॉडल को इंजेक्ट करने का सबसे अच्छा तरीका है?
  • क्या अन्य आईओसी कंटेनरों में ऐसा करने के लिए एक बेहतर (या तेज़) तरीका है, उदा। Autofac?
  • एमईएफ के साथ इस समस्या का सामना कैसे किया जाएगा, यह देखते हुए कि यह एक पारंपरिक आईओसी कंटेनर नहीं है लेकिन अभी भी वस्तुओं को लिखने के लिए उपयोग किया जाता है?

उत्तर

2

कंटेनर आप अपने कारखाने के CreateAddressViewModel विधि में एक पैरामीटर (अन्यथा नामित या) निर्दिष्ट नहीं कर सकते पर निर्भर करता है?

container.Resolve<IAddressViewModel>(new NamedParameterOverloads() { { "Address", model } }; 

कंटेनर के आधार पर अपने कारखाने (afaik TinyIoC और Castle) पैरामीटर का नाम पता करने के लिए हो सकता है, या यह निर्माता निर्भरता (YMMV कंटेनर के आधार पर), की सूची में अंतिम होना था हो सकता है बहुत अच्छा नहीं है, लेकिन यह जल्दी उत्तराधिकार में बहुत सारे बच्चे के कंटेनरों को बचाता है, और जीसी थ्रैशिंग का पालन करेगा, और आप अभी भी अपनी सभी अन्य निर्भरताओं के लिए DI प्राप्त करेंगे।

बेशक यह नीचे गिर जाता है, तो अपने वी एम भी एक निर्भरता है कि एक ही IAddress की आवश्यकता है, उस मामले में एक बच्चे के कंटेनर शायद जाने के लिए जब तक आप वीएम कंटेनर का ज्ञान होना चाहते हैं जिस तरह से है।

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

+0

जैसा कि आप इंगित करते हैं कि निर्दिष्ट पैरामीटर काम नहीं करते हैं अगर किसी भी निर्भरता को मॉडल की आवश्यकता होती है, जो मेरे लिए एक शोस्टॉपर है। बच्चे के कंटेनर का पुन: उपयोग करना एक संभावना है, हालांकि। – GraemeF

0

WPF Application Framework (WAF) का व्यूमोडेल नमूना अनुप्रयोग दिखाता है कि आप मॉडल और व्यूमोडेल को एक साथ कैसे ला सकते हैं। नमूना निर्भरता इंजेक्शन फ्रेमवर्क के रूप में MEF का उपयोग करता है।

+0

नमूने के माध्यम से देखकर मुझे ऐसा कहीं भी नहीं मिला है जो ऐसा करता है - वे एक एकल व्यूमोडेल बनाते हैं और चयन में परिवर्तन के रूप में मॉडल सेट करते हैं। हो सकता है कि मैं सही जगह पर नहीं देख रहा हूं, क्या आप मुझे उस कक्षा में इंगित कर सकते हैं जो आपके मन में था? – GraemeF

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