2010-09-08 17 views
6

मैं कैसे सुनिश्चित कर सकता हूं कि एक निश्चित वर्ग केवल कारखाने द्वारा तत्काल है और नया सीधे कॉल करके नहीं?सुनिश्चित करें कि केवल फैक्ट्री द्वारा निर्मित ऑब्जेक्ट (सी #)

संपादित करें: मैं कारखाने की जरूरत है एक अलग वर्ग (निर्भरता इंजेक्शन प्रयोजनों के लिए) होने के लिए तो मैं यह वर्ग के एक स्थिर विधि instantiated जा करने के लिए नहीं कर सकते हैं, और इसलिए मैं नहीं कर सकता नई निजी।

उत्तर

5

यदि किसी कारण से, आपको कारखाने और निर्मित वर्ग को अलग-अलग असेंबली में होना आवश्यक है (जिसका अर्थ है कि internal का उपयोग केवल काम नहीं करेगा), और आप यह सुनिश्चित कर सकते हैं कि आपके कारखाने को पहले चलाने का मौका मिले, आप यह कर सकते हैं:

// In factory assembly: 

public class Factory 
{ 
    public Factory() 
    { 
     token = new object(); 
     MyClass.StoreCreateToken(token); 
    } 

    public MyClass Create() 
    { 
     return new MyClass(token); 
    } 

    private object token; 
} 

// In other assembly: 

public class MyClass 
{ 
    public static void StoreCreateToken(object token) 
    { 
     if (token != null) throw new InvalidOperationException(
      "Only one factory can create MyClass."); 

     this.token = token; 
    } 

    public MyClass(object token) 
    { 
     if (this.token != token) throw new InvalidOperationException(
      "Need an appropriate token to create MyClass."); 
    } 

    private static object token; 
} 

हाँ, यह बोझिल और अजीब है। लेकिन अजीब स्थितियां हो सकती हैं जहां यह वास्तव में एक अच्छा समाधान है।

+0

मुझे यह पसंद है, सिवाय इसके कि 2 समस्याएं हैं ... (1) आपका उदाहरण मुझे केवल 1 कारखाने का उपयोग करने की अनुमति देता है। मैं कई कारखानों को बनाने की अनुमति देना चाहता हूं (शायद फैक्ट्री के विभिन्न स्वाद हैं) केवल आवश्यकता यह है कि माई क्लास का एक वस्तु फैक्ट्री के किसी ऑब्जेक्ट का उपयोग करके बनाई जानी चाहिए। (2) क्या होगा यदि मैं जेनरिक्स का उपयोग एक नई() बाधा के साथ कर रहा हूं और इस प्रकार MyClass को पैरामीटर रहित कन्स्ट्रक्टर होना चाहिए? आपका उदाहरण उस परिदृश्य में काम नहीं करेगा। – JoelFan

+0

"आपका उदाहरण मुझे केवल 1 कारखाने का उपयोग करने की अनुमति देता है।" 'टोकन' स्थिर बनाएं या इसे विभिन्न फैक्ट्री उदाहरणों के बीच किसी अन्य तरीके से साझा करें। टोकन तक पहुंचने वाली किसी भी चीज को 'MyClass'' के उदाहरण बना सकते हैं, यदि मैं एक नई() बाधा के साथ जेनेरिक का उपयोग कर रहा हूं और इस प्रकार MyClass को पैरामीटर रहित कन्स्ट्रक्टर की आवश्यकता है? " तब आपको कारखाने की जरूरत नहीं है। – munificent

11

अपने रचनाकारों को निजी बनाएं और फैक्ट्री विधि को कक्षा पर एक स्थिर विधि के रूप में आपूर्ति करें।

ज्यादातर मामलों में आप केवल रचनाकारों को आंतरिक बना सकते हैं, जिससे आप फैक्ट्री को अपनी कक्षा में तोड़ सकते हैं - मुझे लगता है कि कक्षा में उदाहरण बनाने के लिए मेरी अपनी टीम को new का उपयोग करने से रोकने की कोशिश करने के लायक नहीं है ' सभा।

5

कन्स्ट्रक्टर आंतरिक बनाएं और उसी असेंबली में फैक्ट्री का घर बनाएं।

public MyClass 
{ 
    internal MyClass() 
    { 
    } 
} 
एक ही विधानसभा

public MyClassGenerator 
{ 
    public static CreateMyClass() 
    { 
     return new MyClass(); 
    } 
} 

में

कारखाने में एक ही विधानसभा में नहीं किया जा सकता या इस विधि Dan's answer

22

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

+0

+1 - अगर आप वास्तव में इस की जरूरत है, यह है कि यह कैसे किया जाना है। –

1

यह हमेशा को कहीं भी पर कॉल करके बनाया जाएगा, लेकिन यदि आप केवल अपने कारखाने वर्ग में ऐसा करना चाहते हैं, तो आप सभी रचनाकारों को आंतरिक (या निजी, और सार्वजनिक स्टेटिक फैक्ट्री विधि का उपयोग कर सकते हैं) एक ही कक्षा)।

0

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

1

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

2

आप अपने कारखाने वर्ग के अंदर सार्वजनिक कन्स्ट्रक्टर के साथ घोंसला वाले निजी वर्गों के रूप में अपनी ठोस कक्षाएं बना सकते हैं - इस तरह आपका कारखाना उन्हें बना सकता है, अन्य लोग उन्हें भी नहीं देख सकते हैं। वैसे भी आप कारखाने से कुछ इंटरफेस/अमूर्त वर्ग, ठोस प्रकार नहीं लौटते हैं। बेशक आप क्लाइंट कोड में कहीं भी अपने रिटर्न प्रकार को कंक्रीट प्रकार में नहीं डाल पाएंगे, लेकिन सबसे पहले यह खराब डिज़ाइन का संकेत है, दूसरा आप इसे हमेशा अपने कंक्रीट इंटरफ़ेस/अमूर्त वर्ग के साथ अपने घोंसला वाले निजी वर्ग विरासत के साथ काम कर सकते हैं ।

आप (एक समान समस्या के लिए) यहाँ एरिक Lippert के जवाब का उल्लेख कर सकते हैं: Why Would I Ever Need to Use C# Nested Classes

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