2013-01-17 26 views
10

के साथ सुरक्षित एनम पैटर्न कार्यान्वयन टाइप करें सामान्य प्रकार पर टाइपएफ़ एनम पैटर्न कैसे कार्यान्वित किया जा सकता है? मान लेते हैं यह इन पंक्तियोंजेनेरिक

public class KnownSetting<T> 
{ 
    public readonly static KnownSetting<String> Name = new KnownSetting<String>("name", "Default Name", t => t); 
    public readonly static KnownSetting<int> Size = new KnownSetting<String>("size", "25", t => Converter.ToInt32); 

    public String Key { get; set; } 
    public T DefaultValue { get; set; } 
    public Func<String, T> Converter { get; set; } 

    private KnownSetting(String key, T defaultValue, Func<String, T> converter) 
    { 
     Key = key; 
     DefaultValue = defaultValue; 
     Converter = converter; 
    } 
} 

पैटर्न के कार्यान्वयन इस तरह से सही है के बाद से निर्माता निजी रहता है, लेकिन जब इस संरचना का उपयोग कर, यह गलत लग रहा है के साथ लागू हो जाता है दो:

public static class Program 
{ 
    public static void main() 
    { 
     var x = KnownSetting<?>.Name; 
    } 
} 

तो एक विकल्प होगा इसे दो में विभाजित करना, ज्ञात सेटिंग कंटेनर क्लास और सेटिंग कार्यान्वयन, लेकिन फिर कंटेनर का दायरा निजी नहीं हो सकता है ताकि कंटेनर के भीतर से तत्काल हो सके।

इस पैटर्न को कैसे कार्यान्वित किया जा सकता है ताकि इसका जेनेरिक पहलू अंत उपयोगकर्ता से छुपा रहता है, लेकिन दृढ़ता से टाइप किया जाता है? क्या कोई और उपयुक्त पैटर्न है, या इसे लागू करने का एक बेहतर तरीका है?

अद्यतन मैंने यह दिखाने के लिए एक दूसरा नमूना जोड़ा कि मैं चाहता हूं कि सेटिंग सामान्य हो।

+4

आपका स्थिर क्षेत्र प्रत्येक 'T' के लिए एक अलग महत्व है। आप वह नहीं चाहते हैं। – SLaks

+0

सबसे अच्छा मैं सोच सकता हूं कि कन्स्ट्रक्टर आंतरिक है और अपने "कंटेनर क्लास" विचार के साथ जाना है, तो आपको केवल उसी असेंबली के भीतर प्रोग्रामर के अनुशासन पर भरोसा करना होगा। –

+0

@Slaks मुझे ऐसा क्यों नहीं चाहिए? – Spooles

उत्तर

4

आधार प्रकार में एक सहायक विधि बनाएं जो किसी अन्य प्रकार का उपयोग करती है और एक ज्ञात सेटिंग क्लास बनाती है। आपको बिल्ड विधि की आवश्यकता है क्योंकि बेस कन्स्ट्रक्टर सेटिंग (स्ट्रिंग, ऑब्जेक्ट, फनक) है। यह भी कारण है कि मैं एक सामान्य चर (यू) परिचय:

public class KnownSetting : Setting<object> 
{ 
    private KnownSetting(string key, object defaultValue, Func<string, object> converter) : base(key, defaultValue, converter) { } 

    public readonly static Setting<string> Name = Create<string>("name", "Default Name", t => t); 
    public readonly static Setting<int> Size = Create<int>("size", 25, t => Convert.ToInt32(t)); 
} 

public class Setting<T> 
{ 
    public string Key { get; set; } 
    public T DefaultValue { get; set; } 
    public Func<string, T> Converter { get; set; } 

    protected static Setting<U> Create<U>(string key, U defaultValue, Func<string, U> converter) 
    { 
     return new Setting<U>(key, defaultValue, converter); 
    } 

    protected Setting(string key, T defaultValue, Func<string, T> converter) 
    { 
     Key = key; 
     DefaultValue = defaultValue; 
     Converter = converter; 
    } 
} 
public static class Program 
{ 
    static void Main(string[] args) 
    { 
     var x = KnownSetting.Name; 
    } 
} 
+0

यह कैसे मदद करता है? पूर्वनिर्धारित एक निजी ctor है, लेकिन अप्रयुक्त। यहां स्थापित करने से सामान्य और निजी सीटीआर की कमी है जो समस्या का मूल है। – Spooles

+0

आप सही हैं, मैंने समस्या को गलत समझा। मैंने समस्या को प्रतिबिंबित करने के लिए अपना समाधान बदल दिया; यह वह जवाब होना चाहिए जिसे वह ढूंढ रहा है। – atlaste

+0

यदि आपके पास संरक्षित है, तो ctor निजी क्यों नहीं है? – Spooles

3

एक नया वर्ग में स्थिर डेटा घोषित:

public class KnownSetting 
{ 
    public readonly static KnownSetting<String> Name = new KnownSetting<String>("name", "Default Name", t => t); 
    public readonly static KnownSetting<int> Size = new KnownSetting<String>("size", "25", t => Converter.ToInt32); 
} 

यह सी # में एक ही नाम हो सकता है क्योंकि वर्ग के नाम नाम के साथ साथ सामान्य प्रकार तर्क गणना पर अद्वितीय हैं।

+1

इसके अतिरिक्त, आप 'ज्ञात सेटिंग ' 'ज्ञात सेटिंग 'से प्राप्त हो सकते हैं, इसलिए एक" सामान्य "गैर-टाइप किया गया फ़ॉर्म है जिसे आप आवश्यकतानुसार एक साथ समूहित कर सकते हैं। – Bobson

+0

लेकिन 'ज्ञात सेटिंग ' के निर्माता को काम करने के लिए जनता की आवश्यकता है। –

+0

@ default.kramer अच्छा बिंदु। हालांकि, यह आंतरिक हो सकता है। – usr

0

शायद मैं कुछ याद कर रहा हूँ, लेकिन क्यों सिर्फ अपने KnownSetting<T> वर्ग के रूप में नए संदर्भ में एक ही enum उदाहरणों के लिए एक नया से उपयोग करते हैं, और नहीं कर सकता कक्षा? की तरह कुछ:

public static class KnownSettings { 
    public readonly static KnownSetting<string> Name = KnownSetting<string>.Name; 
    public readonly static KnownSetting<int> Size = KnownSetting<int>.Size; 
    // etc. 
} 

तो फिर तुम वांछित के रूप में मूल्यों का उपयोग कर सकते हैं:

var x = KnownSettings.Name; 
+0

क्योंकि ज्ञात सेटिंग और ज्ञात सेटिंग (कोई जेनेरिक नहीं) एक ही कक्षा नहीं है, इसलिए गैर-जेनेरिक निजी सीटीओ या सामान्य नहीं देख सकता है। – Spooles

+0

@Spooles: लेकिन इसे कन्स्ट्रक्टर को देखने की आवश्यकता नहीं है, इसे केवल 'सार्वजनिक पठनीय स्थिर' फ़ील्ड को देखने की आवश्यकता है। सभी 'ज्ञात सेटिंग 'मानों को पूरी तरह से' ज्ञात सेटिंग 'के लिए आंतरिक रूप से बनाया जा सकता है, लेकिन ग्राहक अभी भी किसी अन्य वर्ग के किसी अन्य फ़ील्ड के माध्यम से उन मानों तक पहुंच सकते हैं। –