2011-04-04 15 views
6

यह इस प्रश्न का मामूली भिन्नता है: Possible to use a singleton with a non-default constructor in C#?सी # में एक गैर-डिफ़ॉल्ट कन्स्ट्रक्टर वाले सिंगलटन का उपयोग करना संभव है?

मेरे पास एक कक्षा है जो इसके निर्माता के लिए पैरामीटर लेती है। मैं इस सिंगलटन को ऐसा करना चाहता हूं कि सिंगलटन को शुरू करने के लिए पैरामीटर लिया जाता है और इस प्रकार इंस्टेंस पुनर्प्राप्त होने पर हर बार पारित होने की आवश्यकता नहीं होती है।

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

क्या वैसे भी मैं संकलन समय प्रवर्तन के साथ इस व्यवहार को प्राप्त कर सकता हूं? या कम से कम, क्या एक ही काम करने का एक बेहतर तरीका है?

+0

@ user691226 क्या आपको यह कोड करने के लिए कुछ कोड चाहिए पहले से ही, मेरे पास कुछ पॉइंटर्स हो सकते हैं। – msarchet

उत्तर

5

संकलन समय पर ऐसा करने का कोई तरीका नहीं है, क्योंकि यह संकलक पूछने जैसा होगा "क्या आप साबित कर सकते हैं कि कोड एक्स को निष्पादित करने से पहले कभी कोड निष्पादित नहीं किया गया है, कई धागे की उपस्थिति में?"। यह नहीं किया जा सकता है।

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

आप अपने सिंगलटन कक्षा में Func<SingletonType> संपत्ति को उजागर करके इसे थोड़ा बेहतर बना सकते हैं। जब कोई सिंगलटन इंस्टेंस के लिए पूछता है और उदाहरण पहले ही नहीं बनाया गया है, तो आपकी कक्षा सिंगलटन बनाने के लिए इस "फैक्ट्री विधि" को कॉल करेगी। यदि फैक्टरी विधि null है, तो आप या तो कुछ डिफ़ॉल्ट पैरामीटर का उपयोग करके अपवाद फेंक देते हैं या (यदि लागू हो) बनाते हैं।

यह वास्तव में पहली बार आवश्यक होने तक सिंगलटन के निर्माण को रोकता है, इसलिए यह कुछ सुधार है। लेकिन अंतर्निहित सिद्धांत वही है।

अद्यतन:

LukeH के रूप में अंक बाहर, यह बहुत ज्यादा क्या Lazy<T> करता है (.NET 4 केवल) है। यदि संभव हो, तो अपना खुद का लिखने के बजाय उस का उपयोग करें।

+0

उत्तर के लिए धन्यवाद। मुझे लगता है कि मैं उम्मीद कर रहा था कि मैं एक ही व्यवहार को प्राप्त करने का एक पूरी तरह से अलग तरीका याद कर सकता हूं जो मुझे संकलन समय की जांच देता है। – millie

+2

आपने बहुत अधिक वर्णन किया है कि कैसे 'आलसी ' काम करता है: http://msdn.microsoft.com/en-us/library/dd642331.aspx – LukeH

+0

@LukeH: टिप के लिए धन्यवाद, मैंने कभी ऐसा नहीं किया है दूर। – Jon

0

आपके पास GetInstance()CreateInstance() विधि को कॉल कर सकता है यदि सिंगलटन ऑब्जेक्ट पहले से मौजूद नहीं है।

+1

आप ऐसा नहीं कर सकते क्योंकि GetInstance में ऐसे पैरामीटर नहीं हैं जो CreateInstance की आवश्यकता है। – millie

+0

क्या आप निर्धारित कर सकते हैं कि – msarchet

0

मैं इसे इसी तरह से करूँगा। आप यह सुनिश्चित करने के लिए ताले या अन्य चीजें जोड़ने के लिए हो सकता है:

public class ClassA {  
    private static ClassA instance; 

    private int param; 

    private ClassA(int param) { 
     this.param = param; 
    } 

    public static ClassA getInstance() { 
     if (instance == null) { 
      throw new CustomException("Not yet initialised"); 
     } else { 
      return instance; 
     } 
    } 

    public static void createInstance(int param) { 
     if (instance == null) { 
      instance = new ClassA(param); 
     } 
    } 
} 
+1

होने की आवश्यकता क्या है, यह वह कोड है जो मेरे पास पहले से है। दुर्भाग्यवश सवाल यह था कि क्या मैं समय व्यवहार को संकलित करने के लिए इस व्यवहार के रनटाइम प्रवर्तन को बदल सकता हूं। लेकिन यह संभव प्रतीत नहीं होता है। – millie

+0

ओह क्षमा करें, मैंने आपके प्रश्न को गलत समझा। लेकिन नहीं, आप नहीं कर सकते। मुझे लगता है कि ऐसा करने का एकमात्र तरीका यह कम या कम है। –

0

अपने GetInstance() विधि में, क्यों न तुम सिर्फ CreateInstance फोन करता है, तो आपके मान शून्य है, तो आप आलसी initialisation है ..

+0

क्योंकि उसे 'CreateInstance' फ़ंक्शन में तर्क पारित करने की आवश्यकता है। यह पूछे जाने वाले प्रश्न का समाधान प्रदान नहीं करता है। –

+0

वह इन जादुई तर्कों को कहां से प्राप्त कर रहा है यदि उन्हें गेटइन्स्टेंस में पारित नहीं किया गया है, क्योंकि कोई भी GetInstance में पारित नहीं हुआ है, मुझे लगता है कि वे इस बिंदु पर जान जाएंगे .. –

+0

प्रश्न पहले से ही इस पते को संबोधित करता है: * "मेरा समाधान (जो सुरुचिपूर्ण नहीं है) इसके लिए CreateInstance() स्थैतिक विधि है जो पैरामीटर लेती है और सिंगलटन इंस्टेंस का निर्माण करती है। उसके बाद एक और स्थैतिक विधि GetInstance() होगा जो सिंगलटन इंस्टेंस प्राप्त करने के लिए पैरामीटर रहित होगा। "* –

1

एक क्लासिक सिंगलटन में, असली जादूstatic readonly में होता है जो जैसे ही यह प्रयोग किया जाता है उदाहरण बनाता है:

public class MySingleton 
{ 
    private static readonly _instance = new MySingleton(); 

    private MySingleton() {} 

    public static MySingleton Instance 
    { 
     get 
     { 
      return _instance; 
     } 
    } 

} 

आप पैरामीटर हैं तो निर्माता को पारित करने के लिए, आप अपने आप को ताला लगा लागू करना (ध्यान दें डबल iflock sandwitching):

public class MySingletonWithConstructor 
{ 
    private static _instance; 
    private static object _lock = new Object(); 

    private MySingletonWithConstructor(string myArg) 
    { 
     // ... do whatever necessary 
    } 

    public static MySingletonWithConstructor Instance 
    { 
     get 
     { 
      if(_instance==null) 
      { 
       lock(_lock) 
       { 
        if(_instance==null) // double if to prevent race condition 
        { 
         _instance = new MySingletonWithConstructor("Something"); 
        } 
       } 
      } 
      return _instance; 
     } 
    } 

} 
+0

+1 अच्छा ... मैंने कभी भी डबल 'अगर' निर्माण के बारे में सोचा नहीं होगा, और मुझे इसे समझने में लगभग एक मिनट लग गए। सरल और प्रभावी। – corlettk

+0

यह एक पूरी तरह से बेकार निर्माण है क्योंकि यदि सिंगलटन इंस्टेंस गेटर हमेशा "कुछ" (या कुछ अन्य आंतरिक रूप से परिभाषित मूल्य) पास करता है तो 'myArg' पैरामीटर के रूप में कार्य नहीं कर रहा है - कम से कम जहां तक ​​उपभोक्ताओं का संबंध नहीं है - प्रभावी रूप से इस वर्ग में अभी भी एक पैरामीटर रहित कन्स्ट्रक्टर है – BaltoStar

0

उपयोग CreateInstance() एक Lazy<T> का लोडर हो सकता है और के लिए GetInstance सेवानिवृत्त Lazy.Value (आप एक स्थिर रीडोनली फ़ील्ड बनाना चाहते हैं जो = thelazy पर सेट है। CreateInstance() में एक प्रविष्टि सुनिश्चित करने के लिए वैल्यू

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