2012-05-31 9 views
13

का उपयोग करें। क्या यह एक व्यक्तिगत वरीयता है, या कुछ ऐसा जो कक्षाओं को अन्य डी कंटेनरों द्वारा निर्मित करने की अनुमति देता है या वहां [आयात] पर लाभ हैं?मैं क्यों समझने के लिए जब [ImportingConstructor] [आयात] के साथ सजाने गुण की तुलना में अधिक उपयुक्त होगा कोशिश कर रहा हूँ ImportingConstructor

मुझे लगता है कि होता है कि शायद अगर आप सार्वजनिक संपत्तियों का खुलासा नहीं करना चाहता था लेकिन MEF भी है, तो फिर से निजी क्षेत्रों का समाधान हो जाएगा, जहां लाभ है?

उत्तर

21

[Import] का उपयोग करने में समस्या यह है कि यह किसी ऑब्जेक्ट को दो अलग-अलग और देखने योग्य चरणों में विभाजित करता है: बनाया और प्रारंभ किया गया। कहाँ [ImportingConstructor] इस बिल्कुल के रूप में यह हर दूसरे नेट वस्तु के लिए होगा एक एकल चरण के रूप में रहने के लिए अनुमति देता है।

यह अंतर तरीके

  1. एक प्रकार की तार्किक अनुबंध परिवर्तन एक क्षेत्र पर एक नया [Import] जोड़ा जा रहा है की संख्या में नमूदार हो जाता है। फिर भी यह सार्वजनिक या उपयोग अनुबंध नहीं बदलता है। इसका मतलब है कि पहले से संकलित कोई भी कोड संकलित करना जारी रखेगा, भले ही ऑब्जेक्ट निर्भरता बदल गई हो (सोचें यूनिट परीक्षण)। यह संकलन समय त्रुटि क्या होनी चाहिए और इसे रनटाइम बनाता है।
  2. कोड संविदा व्यर्थ कर रहे हैं अगर आप एक [Import] है। अनुबंध सत्यापन इंजन को ठीक स्वीकार करता है कि सभी क्षेत्रों null मूल्यों के रूप में मौजूद कर सकते हैं और एक क्षेत्र के हर उपयोग करने से पहले एक जांच की आवश्यकता होगी।
  3. भले ही आपके वस्तु तार्किक क्षेत्रों जो प्रारंभ समय पर सेट कर रहे हैं और कभी नहीं कर सकते हैं बाद में रीसेट, आप के रूप में आप एक सामान्य सी # वस्तु के साथ होता readonly के साथ इस व्यक्त नहीं कर सकते।
+0

+1 # 1 अब इतना स्पष्ट प्रतीत होता है। मैं कोड अनुबंध मुद्दे से अनजान था। क्या आप # 3 थोड़ा और समझा सकते हैं? – ILovePaperTowels

+3

@ILovePaperTowels # 3 के संबंध में, मेरे अनुभव में अधिकांश समय आप 'आयात ['] करते हैं, यह एक फ़ील्ड के लिए है जो एक बार सेट कभी नहीं बदलेगा। सी # में यह क्षेत्र को 'रीडोनली' बनाकर व्यक्त किया जाता है लेकिन यह '[आयात] 'मामले में काम नहीं करता है क्योंकि कन्स्ट्रक्टर खत्म होने के बाद फ़ील्ड असाइन की जाती है जो' readonly' का उल्लंघन है। यह वास्तव में (और स्काई) प्रतिबिंब के माध्यम से काम करेगा लेकिन गैर-एमईएफ संरचना के साथ इसका उपयोग लगभग असंभव – JaredPar

2

[ImportingConstructor] का उपयोग करके, आप एक वर्ग को अपनी निर्भरताओं को आयात करने के लिए निर्यात के रूप में कार्य करने की अनुमति देते हैं। यह नाटकीय रूप से आर्किटेक्चर को सरल बनाता है, क्योंकि आप अपने कार्यान्वयन से ठोस वस्तु की निर्भरताओं को कम कर सकते हैं।

आम तौर पर, आप [ImportingConstructor] का उपयोग उस प्रकार पर करते हैं, जिसे स्वयं [Export] के रूप में चिह्नित किया गया है। जब टाइप रचित होता है, तो कन्स्ट्रक्टर तर्क एमईएफ द्वारा प्रदान किए जाएंगे।

+0

है, यह गारंटी है कि निर्यात के आयात को हल करने से पहले आवश्यक आयात उपलब्ध हैं? – ILovePaperTowels

+0

@ILovePaperTowels हां, इसके बिना, आपको किसी आयात में ऑब्जेक्ट बनाना होगा, इसे अमान्य स्थिति में रखना होगा, फिर निर्भरताओं को भरने के लिए इसे पुन: संयोजित करें, फिर प्रारंभिकरण के कुछ रूप को कॉल करें ... यह बहुत बदसूरत है। –

8

एमईएफ के संदर्भ में पूरी तरह से सोचने के बजाय, अपने वर्ग के डिजाइन को व्यापक रूप से देखें। आम तौर पर जब आप एक वर्ग को डिजाइन कर रहे हैं, आप संबद्ध गुण का एक सेट है, इन सेवाओं हो सकता है, जैसे,

public class MyService 
{ 
    public ILogger Logger { get; set; } 

    public void SaySomething() 
    { 
    Logger.Log("Something"); 
    } 
} 

अब, मैं आगे जाना है और इस बात का एक उदाहरण बना सकते हैं:

var service = new MyService(); 

और अब, अगर मैं कोशिश करते हैं और विधि का उपयोग करें:

service.SaySomething(); 

मैं स्पष्ट रूप से मैं अपने Logger संपत्ति आरंभ करने के लिए है कि पता नहीं है:

var service = new MyService() { Logger = new ConsoleLogger() }; 

(या):

var service = new MyService(); 
service.Logger = new ConsoleLogger(); 

तो त्रुटि क्रम जब तक स्पष्ट नहीं हो जाएगा।हम वर्ग को फिर से परिभाषित करना हो तो: अब

public class MyService 
{ 
    private readonly ILogger _logger; 

    public MyService(ILogger logger) 
    { 
    if (logger == null) throw new ArgumentNullException("logger"); 

    _logger = logger; 
    } 

    public void SaySomething() 
    { 
    _logger.Log("Something"); 
    } 
} 

, अगर आप कोशिश करते हैं और MyService का एक उदाहरण बनाने के लिए, आप स्पष्ट रूप से के लिए वस्तु को सही ढंग से initialised जा करने के लिए इस अतिरिक्त सेवा (ILogger) प्रदान करने के लिए है। इस तरीके का एक संख्या में मदद करता है:

  1. आप निर्भरता अपने प्रकार की आवश्यकता है व्यक्त करते हैं, और यह एक initialisation अनुबंध है कि प्रकार एक प्रयोग करने योग्य राज्य में बनाई गई है सुनिश्चित करने के लिए संतुष्ट होना चाहिए रूपों।
  2. सेवाएं सुनिश्चित करने के द्वारा आप रनटाइम त्रुटियों का जोखिम कम कर देते हैं।

संकलन समय पर स्थिर जांच करने के लिए आप कोड अनुबंध (जैसा कि @ जेरेडपार द्वारा उल्लिखित) का उपयोग करके इस डिजाइन पर अधिक सुधार कर सकते हैं।

MEF के संदर्भ में, आप ([ImportingConstructor]) [Import] बजाय [ImportingConstructor] MEF के रूप में उपयोग करके अपवाद फेंक जब यह एक प्रकार पर सभी आयातों को संतुष्ट नहीं कर सकते हैं के साथ भाग प्राप्त कर सकते हैं, और केवल प्रकार वापस आ जाएगी दोनों initialisation के बाद और फिर [Import] रों।

कन्स्ट्रक्टर इंजेक्शन आम तौर पर बेहतर होता है।

0

पुनर्गठन कन्स्ट्रक्टर पैरामीटर पर भी समर्थित नहीं है।