33

मानक नौसिखिया अस्वीकरण: मैं आईओसी के लिए नया हूं और मिश्रित सिग्नल प्राप्त कर रहा हूं। मैं निम्नलिखित स्थितियों पर कुछ मार्गदर्शन की तलाश में हूं।क्या आईओसी कंटेनर का उपयोग करते समय आदिम कन्स्ट्रक्टर पैरामीटर एक बुरा विचार है?

मान लीजिए मैं निम्नलिखित इंटरफेस और कार्यान्वयन:

public interface IImageFileGenerator 
{ 
    void RenameFiles(); 
    void CopyFiles(); 
} 

public class ImageFileGenerator : IImageFileGenerator 
{ 
    private readonly IList<IImageLink> _links; 
    private readonly string _sourceFolder; 
    private readonly string _destinationFolder; 
    private readonly int _folderPrefixLength; 

    public ImageFileGenerator(IList<IImageLink> links, string sourceFolder, string destinationFolder) 
    { 
     _links = links; 
     _sourceFolder = sourceFolder; 
     _destinationFolder = destinationFolder; 
     _folderPrefixLength = 4; 
    } 

    public void RenameFiles() 
    { 
     // Do stuff, uses all the class fields except destination folder 
    } 

    public void CopyFiles() 
    { 
     // Do stuff, also uses the class fields 
    } 
} 

मैं उलझन में हो रही है कि क्या मैं केवल, निर्माता के लिए इंटरफ़ेस/निर्भरता भेज कुछ पैरामीटर वस्तु बना सकते हैं और यह निर्माता को पारित या इसे रखना चाहिए एक उदाहरण को हल करने के समय पैरामीटर में है और पास है।

तो क्या आईओसी कंटेनर के साथ सबसे अच्छा काम करने के लिए इस कोड को स्थापित करने का एक और सही तरीका है? क्या इनमें से कोई भी मेरे वर्तमान लेआउट पर डिजाइन-वार पसंद किया जाएगा?

1.

public interface IImageFileGenerator 
{ 
    void RenameFiles(IList<IImageLink> links, string sourceFolder); 
    void CopyFiles(IList<IImageLink> links, string sourceFolder, stringDestFolder); 
} 

public class ImageFileGenerator : IImageFileGenerator 
{ 
    private readonly int _folderPrefixLength; 

    public ImageFileGenerator() 
    { 
     _folderPrefixLength = 4; 
    } 

    public void RenameFiles(IList<IImageLink> links, string sourceFolder) 
    { 
     // Do stuff 
    } 

    public void CopyFiles(IList<IImageLink> links, string sourceFolder, stringDestFolder) 
    { 
     // Do stuff 
    } 
} 

मुझे पसंद नहीं है कि मैं दोनों ही मामलों में सटीक एक ही बात में गुजर रहा हूँ (गंतव्य फ़ोल्डर को छोड़कर)। IImageFileGenerator के वर्तमान कार्यान्वयन में, मुझे दोनों विधियों को निष्पादित करने की आवश्यकता है और प्रत्येक विधि के लिए समान मूल्यों की आवश्यकता थी। यही कारण है कि मैंने राज्य को कन्स्ट्रक्टर के माध्यम से पारित किया।

2.

public interface IImageFileGenerator 
{ 
    void RenameFiles(); 
    void CopyFiles(); 
} 

public class ImageLinkContext 
{ 
    // various properties to hold the values needed in the 
    // ImageFileGenerator implementation. 
} 

public class ImageFileGenerator : IImageFileGenerator 
{ 
    private readonly IList<IImageLink> _links; 
    private readonly string _sourceFolder; 
    private readonly string _destinationFolder; 
    private readonly int _folderPrefixLength; 

    public ImageFileGenerator(ImageLinkContext imageLinkContext) 
    { 
     // could also use these values directly in the methods 
     // by adding a single ImageLinkContext field and skip 
     // creating the other fields 
     _links = imageLinkContext.ImageLinks; 
     _sourceFolder = imageLinkContext.Source; 
     _destinationFolder = imageLinkContext.Destination; 
     _folderPrefixLength = 4; 
    } 

    public void RenameFiles() 
    { 
     // Do stuff, uses all the class fields except destination folder 
    } 

    public void CopyFiles() 
    { 
     // Do stuff, uses all the class fields 
    } 
} 

यह दृष्टिकोण भी एक फसाड सेवा (पहले कुल सेवाओं कहा जाता है) के रूप में मार्क सीनैन here ने उल्लेख करने के लिए बदलाव किया जा सकता है।

मैंने यह भी पढ़ा है कि आप उन मूल्यों के लिए गुणों का उपयोग कर सकते हैं और संपत्ति इंजेक्शन का उपयोग कर सकते हैं, हालांकि ऐसा लगता है कि अब इसे पसंद नहीं किया जाता है (ऑटोफैक का उल्लेख है कि कन्स्ट्रक्टर इंजेक्शन को प्राथमिकता दी जाती है ... निनजेक्ट मेरा मानना ​​है कि संस्करण में क्षमता को भी हटा दिया गया है 2)।

वैकल्पिक रूप से मैंने पढ़ा है कि आप प्रारंभिक विधि भी बना सकते हैं और यह सुनिश्चित कर सकते हैं कि गुण वहां सेट हैं।

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

मुझे अब एहसास है कि यह प्रश्न शायद व्यक्तिपरक पक्ष पर थोड़ा सा है (और वास्तव में एक से अधिक प्रश्न है), लेकिन मुझे उम्मीद है कि आप मुझे माफ कर सकते हैं और कुछ मार्गदर्शन प्रदान कर सकते हैं।

पीएस - मैं वर्तमान में ऑटोफैक के साथ अपना हाथ आजमाने की कोशिश कर रहा हूं, जिससे प्रभाव बेहतर हो सकता है कि कौन सा डिज़ाइन बेहतर हो सकता है।

नोट: मैंने गंतव्य फ़ोल्डर के बारे में कोड में थोड़ा बदलाव किया है ... इसका उपयोग RenameFiles द्वारा नहीं किया जा सकता है (आपके उत्तर पर असर हो सकता है)।

+1

इंजेक्शन * सेवाओं * बनाम * डेटा * पर इंजेक्शन पर एक संबंधित चर्चा है: http://stackoverflow.com/questions/1818539/how-to-pass-controllers-modelstate-to-my-service-constructor-with-autofac –

+0

@ पीटर लिलाववॉल्ड: दिलचस्प, मैं फैक्ट्री प्रतिनिधियों को देखने में कुछ समय व्यतीत करूंगा। मैं उन्हें आसानी से आ रहा देख सकता हूं। लिंक के लिए धन्यवाद (और आपके उत्तर में संलग्न आलेख: http://peterspattern.com/generate-generic-factories-with-autofac/)। –

उत्तर

17

ठीक है, मैंने Dependency Injection in .Net पुस्तक पढ़ने के बाद इसे फिर से डिजाइन किया है (मैं इस पुस्तक को किसी भी ऑब्जेक्ट उन्मुख डेवलपर को सलाह देता हूं, न केवल डेवलपर्स और न केवल आईओसी कंटेनर का उपयोग करने में रुचि रखने वाले!)।

मैं अब मिल गया है एक डोमेन विधानसभा में निम्नलिखित:

public class ImageFileService : IImageFileService 
{ 
    public ImageFileService(IImageLinkMapRepository repository) 
    { 
     // null checks etc. left out for brevity 
     _repository = repository; 
    } 

    public void RenameFiles() 
    { 
     // rename files, using _repository.GetImageLinks(), which encapsulates 
     // enough information for it to do the rename operations without this 
     // class needing to know the specific details of the source/dest dirs. 
    } 

    public void CopyFiles() 
    { 
     // same deal as above 
    } 
} 

तो अनिवार्य रूप से, मैं कर दिया है:

public interface IImageFileService 
{ 
    void RenameFiles(); 
    void CopyFiles(); 
} 

public interface IImageLinkMapRepository 
{ 
    IList<ImageLink> GetImageLinks(); 
} 
फिर एक FileAccess विधानसभा मैं इन इंटरफेस के लिए कार्यान्वयन बना लिया है में

कम से कम इस वर्ग के लिए, मेरे कन्स्ट्रक्टर में आदिम प्रकारों की आवश्यकता को हटा दिया। किसी बिंदु पर मुझे उस जानकारी की आवश्यकता थी, लेकिन इसे ImageLinkMapRepository में इंजेक्शन दिया गया था जहां जानकारी अधिक समझ में आई थी। मैंने इंजेक्शन को संभालने के लिए autofac named parameters का उपयोग किया।

तो मुझे लगता है कि मेरे अपने प्रश्न का उत्तर देने के लिए, आदिम कन्स्ट्रक्टर पैरामीटर एक अच्छा विचार हैं यदि वे समझ में आते हैं, लेकिन सुनिश्चित करें कि आप उन्हें कहां रखते हैं। अगर चीजें ठीक से जिंगिंग नहीं लगती हैं, तो संभवतः डिजाइन पर पुनर्विचार करके इसे बेहतर किया जा सकता है।

2

अपने उदाहरण में क्या आप वास्तव में से गुजर रहे हैं निर्भरता, लेकिन इसके अलावा डेटा वर्ग द्वारा आवश्यक संचालित करने के लिए कर रहे हैं।

आपके मामले में यह RenameFiles() और CopyFiles() विधियों की तरह लगता है जो उन्हें पारित पैरामीटर पर काम करते हैं।उनके नाम मुझे लगता है कि ImageFileGenerator के एक उदाहरण पर विधियों को विभिन्न मानकों के साथ बुलाया जा सकता है। यदि यह सच है तो पैरामीटर विधि पर होना चाहिए स्वयं को कन्स्ट्रक्टर नहीं कहता है।

यदि दूसरी ओर, एक उदाहरण पर RenameFiles() और CopyFiles() प्रत्येक को केवल एक ही पैरामीटर के साथ बुलाया जाता है तो पैरामीटर कन्स्ट्रक्टर के लिए अच्छे उम्मीदवार होंगे।

मैं व्यक्तिगत रूप से निर्भरताओं के लिए संपत्ति इंजेक्शन से बचने की कोशिश करता हूं - उस स्थिति में कन्स्ट्रक्टर इंजेक्शन अधिक उपयुक्त है।

+0

वर्तमान उपयोग यह है कि दोनों को केवल एक बार और समान पैरामीटर मानों के साथ बुलाया जाता है। और यह * संभावना * है कि हम हमेशा ** RenameFiles ** को कॉल करेंगे, और तत्काल बाद, ** CopyFiles ** को कॉल करें। मुझे लगता है कि मैं उन्हें एक सार्वजनिक विधि में जोड़ सकता हूं और फिर उन दोनों को निजी बना सकता हूं। मैं आसान इकाई परीक्षण के लिए कार्यक्षमता को विभाजित करने की कोशिश कर रहा था। –

+0

@ जेसनडाउन: उस मामले में मुझे लगता है कि आपने अपने प्रश्न का उत्तर दिया है। इसके अलावा यदि आपके द्वारा पास किए गए डेटा पर वास्तव में केवल एक ही ऑपरेशन है तो आप इसे एक स्थिर विधि में ले जा सकते हैं। – BrokenGlass

+0

निश्चित रूप से कुछ विचार करने के लिए। लोड सोच रहा है ... वास्तव में एक अच्छा मौका है कि इंटरफ़ेस का एक और कार्यान्वयन आवश्यक होगा जो केवल छवियों की प्रतिलिपि बनाएगा ... और इसमें एक अलग स्रोत और गंतव्य होगा (यह * प्रतिलिपि * छवियों की प्रतिलिपि होगी, लेकिन प्रतियां एक थंबनेल आकार में परिवर्तित किया जाएगा)। तो शायद प्रत्येक विधि में पैरामीटर को पारित करने का तरीका है। –