6

निनजेक्ट में, सिंगलटन स्कोप में बाध्यकारी घोषित करने का अर्थ है कि एक ही वस्तु हर बार लौटा दी जाएगी। कभी भी एक वस्तु हो सकती है।एक निंजा कस्टम स्कोप कैसे बनाया जाए जो उस ऑब्जेक्ट का निपटारा होने तक वही ऑब्जेक्ट देता है?

मुझे क्या चाहिए एक समय में एक वस्तु को वापस करना है। दूसरे शब्दों में:

  1. प्राप्त करने के लिए पहला कॉल() एक नई वस्तु को तुरंत चालू करता है और इसे वापस करता है।
  2. बाद में कॉल() को एक ही उदाहरण वापस प्राप्त करने के लिए कॉल करें।
  3. ऑब्जेक्ट का निपटारा किया गया है।
  4. ऑब्जेक्ट के बाद प्राप्त करने के लिए पहला कॉल एक नया/दूसरा ऑब्जेक्ट तत्काल करता है और उसे देता है।
  5. बाद कॉल प्राप्त करने के लिए() चरण में बनाए गए ऑब्जेक्ट प्रदान 4.

संपादित करें: यह समस्या वास्तव में नहीं बल्कि providers का उपयोग कर और जब निपटारा प्रश्न में वस्तु एक घटना बढ़ा होने का उपयोग कर हल करने के लिए सरल है। निंजा में स्कॉप्स का उपयोग करके ऐसा करने का कोई तरीका था, तो मैं उत्सुक था, और इस प्रश्न को यहां छोड़ दूंगा क्योंकि स्टीवन का जवाब उत्कृष्ट है।

+0

आप किस प्रकार का आवेदन चला रहे हैं? क्या यह एक बहु थ्रेडेड एप्लीकेशन है? – Steven

+0

हां। उदाहरण प्रति थ्रेड की तरह कुछ उपयोगी नहीं होगा। – anthony

उत्तर

6

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

आप दौड़ की स्थिति के कारण निपटान के बाद ऑब्जेक्ट को नवीनीकृत करने के लिए कॉन्फ़िगर नहीं कर सकते हैं। निम्नलिखित परिदृश्य की कल्पना करें:

  1. थ्रेड 1 कंटेनर से एक उदाहरण का अनुरोध करता है।
  2. यह पहला अनुरोध है और कंटेनर एक नया उदाहरण बनाएगा।
  3. थ्रेड 2 कंटेनर उदाहरण चरण में बनाए गए 2.
  4. थ्रेड 1 उदाहरण के साथ किया और Dispose कॉल रिटर्न कंटेनर
  5. से एक उदाहरण अनुरोध करता है।
  6. थ्रेड 2 उदाहरण का उपयोग शुरू करता है, लेकिन उदाहरण का निपटारा किया जाता है, और अपवाद फेंकता है।

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

यदि आप कर सकते हैं तो अपने आवेदन को फिर से डिजाइन करके इसे करने से रोकने का प्रयास करें। IDisposable को लागू करने वाले सेवा प्रकारों का पर्दाफाश करना एक बुरा अभ्यास है, क्योंकि IDisposable एक रिसाव अमूर्त है। IDisposable को लागू करने के लिए इन सेवाओं के किसी भी कार्यान्वयन को रोकने के लिए भी मेरी व्यक्तिगत वरीयता है। ज्यादातर परिदृश्यों में एक नया स्वरूप आपको ऐसा करने से रोक सकता है।

यदि आपको IDisposable ऑब्जेक्ट्स का उपयोग करने की आवश्यकता है, तो ऐसा करने का सामान्य तरीका इन IDisposable ऑब्जेक्ट्स बनाने वाली फैक्ट्रियों को बनाना और इंजेक्ट करना है। इस तरह उपभोक्ता किसी भी समस्या के बिना सुरक्षित रूप से ऐसी वस्तु का निपटान कर सकता है।

सामान्य समस्या यह है कि IDisposable लागू करने वाली वस्तुओं को बनाना मुश्किल है, जो वास्तव में थ्रेड-सुरक्षित हैं।

यदि आप वास्तव में यह चाहते हैं, तो आप एक सजावट बनाने की कोशिश कर सकते हैं जो संदर्भ गणना करता है। नीचे सजावट पर उदाहरण के लिए देखो। यह IService लपेटता है और IService लागू करता है। IService लागू IDisposable। सजावटी Func<IService> प्रतिनिधि जो उदाहरणों के निर्माण की अनुमति देता है। वस्तुओं का निर्माण और निपटान lock कथन द्वारा संरक्षित है और सजावटी कॉलर्स द्वारा संदर्भों की गणना करता है। अंतिम उपभोक्ता सजावट का निपटारा करने के बाद, यह ऑब्जेक्ट का निपटान करेगा और एक नया निर्माण करेगा।

public class ScopedServiceDecorator : IService 
{ 
    private readonly object locker = new object(); 
    private Func<IService> factory; 
    private IService currentInstance; 
    private int referenceCount; 

    public ScopedServiceDecorator(Func<IService> factory) 
    { 
     this.factory = factory; 
    } 
    public void SomeOperation() 
    { 
     IService instance; 
     lock (this.locker) 
     { 
      instance = this.GetInstance(); 
      this.referenceCount++; 
     } 

     instance.SomeOperation(); 
    } 

    public void Dispose() 
    { 
     IService instance = null; 

     lock (this.locker) 
     { 
      this.referenceCount--; 

      if (this.referenceCount == 0) 
      { 
       instance = this.wrappedService; 
       this.wrappedService = null; 
      } 
     } 

     // Dispose the object outside the lock for performance. 
     if (instance != null) 
     { 
      instance.Dispose(); 
     } 
    } 

    private IService GetInstance() 
    { 
     if (this.wrappedService == null) 
     { 
      this.wrappedService = this.factory(); 
     } 

     return this.wrappedService; 
    } 
} 

कृपया ध्यान दें कि इस कार्यान्वयन अभी भी त्रुटिपूर्ण है, ऐसा निम्न कारणों से:

  1. कॉलिंग Dispose कई बार डेकोरेटर टूट जाता है।
  2. जब उपभोक्ता SomeOperation कई बार कॉल करते हैं (या IService में कई विधियां हैं) कार्यान्वयन टूट जाएगा।

एक सजावट बनाने वाला बहुत कठिन है जो अपेक्षित कार्य करता है। ऐसा करने का एक आसान तरीका ऑब्जेक्ट तक पहुंच को क्रमबद्ध करना है, लेकिन जब आप ऐसा करते हैं, तो संभवतः आप प्रति थ्रेड के एक उदाहरण का उपयोग करना चाहते हैं। यह बहुत आसान होगा।

मुझे उम्मीद है कि इससे मदद मिलती है।

+0

आप एक लापरवाही अमूर्त होने के लिए IDisposable क्यों विचार करते हैं? (मैं आप का विरोध नहीं कर रहा हूं, मैं शुद्ध ब्याज से पूछता हूं) –

+0

@ जोहान: मार्क सेमैन से इन उत्तरों पर एक नज़र डालें: http://stackoverflow.com/questions/2634675/ioc-containers-and-idisposable/2635733# 2635733 और http://stackoverflow.com/questions/2404007/di-with-disposable-objects/2404104#2404104। – Steven

+1

धन्यवाद! एसओ पर, मार्क सीमन आईओसी और डी के लिए है जो जॉन स्कीट सी # के लिए है :) मुझे विशेष रूप से पसंद आया * "... आपके मन में एक विशेष कार्यान्वयन है। इसलिए, कार्यान्वयन अमूर्तता में लीक हो जाता है।" * Http: // पर stackoverflow.com/questions/2634675/ioc-containers-and-idisposable/2635733#2635733 –

1

मुझे पता है कि यह हल हो गया है लेकिन ... @ स्टीवन का जवाब यह इंगित नहीं करता है कि निनजेक्ट में InScope तंत्र है जो आप जो खोज रहे हैं उसके पहलुओं को संबोधित करते हैं।

कैसे scoping Ninject 2.

अगला में किया जा सकता फिर से नैट Kohari के Cache and Collect लेख पर एक नज़र डालें, Ninject स्रोत को देखने जा सकते हैं और देखते हैं कि कैसे InRequestScope कार्यान्वित किया जाता है (सहित कैसे टियरडाउन में झुका है)। 2.3-4 के लिए कुछ काम करने की योजना बनाई गई है जो सामान्यीकृत करने के लिए काम करता है कि यह कुछ जटिल होस्टिंग परिदृश्यों के लिए उपयोग करने की अनुमति देता है।

जब आपने इन दो संदर्भों को देखा है, तो निंजा मेलिंग सूची पर एक प्रश्न पूछें और आपको निश्चित रूप से समाधान मिलेगा।