13

मैं माइक्रोसॉफ्ट के यूनिटी फ्रेमवर्क के साथ सी # का उपयोग कर रहा हूं। मुझे पूरा यकीन नहीं है कि इस समस्या को कैसे हल किया जाए। यह शायद एकता के साथ डी समझने की कमी के साथ कुछ करने के लिए है।सी #/एकता में कन्स्ट्रक्टर इंजेक्शन?

मेरे समस्या निम्न उदाहरण कोड का उपयोग कर अभिव्यक्त किया जा सकता:

class Train(Person p) { ... } 

class Bus(Person p) { ... } 

class Person(string name) { ... } 

Person dad = new Person("joe"); 
Person son = new Person("timmy"); 

जब मैं बस पर संकल्प विधि कॉल कैसे मुझे यकीन है कि हो सकता है कि नाम 'टिम्मी' के साथ व्यक्ति 'बेटा' इंजेक्ट किया जाता है और ट्रेन को हल करते समय मैं कैसे सुनिश्चित कर सकता हूं कि उस नाम के साथ व्यक्ति 'पिता' का हल हो जाए?

मुझे लगता है कि शायद नामित उदाहरणों का उपयोग कर रहे हैं? लेकिन मैं एक नुकसान में हूँ। किसी भी सहायता की सराहना की जाएगी।

एक तरफ के रूप में, मैं एक आईपर्सन इंटरफेस नहीं बनाऊंगा।

उत्तर

15

इसे हल करने का एक तरीका एक नामित पंजीकरण के साथ एक इंजेक्शन कन्स्ट्रक्टर का उपयोग करना होगा।

// Register timmy this way 
Person son = new Person("Timmy"); 
container.RegisterInstance<Person>("son", son); 

// OR register timmy this way 
container.RegisterType<Person>("son", new InjectionConstructor("Timmy")); 

// Either way, register bus this way. 
container.RegisterType<Bus>(new InjectionConstructor(container.Resolve<Person>("son"))); 

// Repeat for Joe/Train 
+2

हार्डकोडिंग की बजाय कॉन्फ़िगरेशन फ़ाइल में इन्हें स्टोर करना संभव कैसे होगा? –

32

जब तक आप क्रमशः रजिस्टर "जो" और नामित निर्भरता के रूप में "टिम्मी", तो आप यह सुनिश्चित करें कि "टिम्मी" Schoolbus में इंजेक्ट किया जाता नहीं हो सकता। वास्तव में, यदि आप समान वर्ग के दो उदाहरणों को अनामित निर्भरताओं के रूप में पंजीकृत करने का प्रयास करते हैं, तो आपके पास एक अस्पष्ट सेटअप होगा, और आप Person को हल करने में सक्षम नहीं होंगे।

सामान्यतः, यदि आपको बहुत से नामांकित उदाहरण पंजीकृत करना है तो आप शायद गलत तरीके से DI के बारे में जा रहे हैं। डीआई का मुख्य विचार डोमेन सेवाओंडोमेन ऑब्जेक्ट से अधिक हल करना है।

डि के प्राथमिक विचार के लिए एक तंत्र है कि आप (इंटरफेस या अमूर्त वर्ग) ठोस प्रकार में सार प्रकार हल करने की अनुमति देता है प्रदान करना है। आपके उदाहरण में कोई सार प्रकार नहीं है, इसलिए यह वास्तव में बहुत अधिक समझ में नहीं आता है।

+0

आपकी अंतर्दृष्टि प्रतिक्रिया के लिए धन्यवाद। यद्यपि आप सही हो सकते हैं, डीआई और आईओसी मेरे लिए नई अवधारणाएं हैं इसलिए मैं अभी भी सर्वश्रेष्ठ डिजाइन को समझने की कोशिश कर रहा हूं। –

+1

यह काफी उचित है - आप मेरी पुस्तक पढ़ना चाहेंगे, फिर :) –

+2

जेपी, अपनी पुस्तक देखें। मैंने इसे बहुत अंतर्दृष्टिपूर्ण पाया है। –

14

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

मेरा व्यक्तिगत इतिहास: मैंने ऑब्जेक्ट निर्माण और नियंत्रण में उलझन के सिद्धांतों को सीखा है इससे पहले कि मैंने एकता या कैसल विंडसर कंटेनर जैसे नियंत्रण कंटेनरों में उलटा उपयोग करने के बारे में सीखा। मैंने इस तरह के कोड लिखने की आदत हासिल की:

public class Foo 
{ 
    IService _service; 
    int _accountNumber; 

    public Foo(IService service, int accountNumber) 
    { 
     _service = service; 
     _accountNumber = accountNumber; 
    } 
    public void SaveAccount() 
    { 
     _service.Save(_accountNumber); 

    } 
} 
public class Program 
{ 
    public static void Main() 
    { 
     Foo foo = new Foo(new Service(),1234); 
     foo.Save(); 
    } 
} 

इस डिज़ाइन में, मेरा Foo क्लास डेटाबेस में खातों को सहेजने के लिए ज़िम्मेदार है। ऐसा करने के लिए इसे एक खाता संख्या और गंदे काम करने की सेवा की आवश्यकता है। यह कुछ हद तक ऊपर दिए गए कंक्रीट वाले वर्गों के समान है, जहां प्रत्येक ऑब्जेक्ट कन्स्ट्रक्टर में कुछ अद्वितीय मान लेता है। यह ठीक काम करता है जब आप ऑब्जेक्ट को अपने कोड से तुरंत चालू करते हैं। आप सही समय पर उचित मूल्यों में गुजर सकते हैं।

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

public class Foo 
{ 
    IService _service; 
    public Foo(IService service) 
    { 
     _service = service; 
    } 
    public void SaveAccount(int accountNumber) 
    { 
     _service.Save(accountNumber); 

    } 
} 
public class Program 
{ 
    public static void Main() 
    { 
     Foo foo = new Foo(new Service()); 
     foo.Save(1234); 
    } 
} 

यह दोनों दिखाई देने वाले फू कक्षाएं वैध डिजाइन हैं। लेकिन दूसरा स्वचालित निर्भरता इंजेक्शन के साथ प्रयोग योग्य है, और पहला नहीं है।

+4

दूसरी मुख्य() विधि अधिक नहीं होनी चाहिए: Foo foo = new foo (नई सेवा()); foo.Save (1234); ? – McBainUK

+0

तथ्य की बात यह है कि यह foo.SaveAccount (1234) :) – sethidev

+0

वहां 'int' प्रारंभिकरण के बारे में दिलचस्प नहीं है। मेरे पास अभी भी एक बहुत ही मामला था (पूरी तरह से अलग डोमेन) जहां मुझे टाइमआउट शुरू करने की आवश्यकता थी - एक विधि के बारे में बताया गया है, – Thomas

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