2010-04-09 17 views
7

ठीक है, तो जैसा कि आप शायद जानते हैं, सी # में स्थिर विरासत असंभव है। मैं समझता हूं कि, हालांकि मैं अपने कार्यक्रम के विकास से फंस गया हूं।सी # स्टेटिक विरासत की कमी - मुझे क्या करना चाहिए?

मैं इसे यथासंभव सरल बनाने की कोशिश करूंगा। आइए कहें कि हमारे कोड को उन ऑब्जेक्ट्स को प्रबंधित करने की आवश्यकता है जो कुछ हवाईअड्डे में एयरक्राफ्ट पेश कर रहे हैं। आवश्यकताओं इस प्रकार हैं:

  • सदस्यों और तरीकों कि सभी विमान

  • विमानों के कई प्रकार के होते हैं के लिए साझा कर रहे हैं कर रहे हैं, प्रत्येक प्रकार के अपने स्वयं के अतिरिक्त तरीकों और सदस्यों हो सकता है। प्रत्येक विमान प्रकार के लिए कई उदाहरण हो सकते हैं।

  • हर विमान प्रकार इस प्रकार के लिए एक दोस्ताना नाम होना आवश्यक है, और इस प्रकार के बारे में अधिक जानकारी। उदाहरण के लिए एफ 16 नामक एक वर्ग के पास "लॉकहीड मार्टिन एफ -16 फाइटिंग फाल्कन" के मूल्य के साथ एक स्थिर सदस्य फ्रेंडलीनाम होगा।

  • अन्य प्रोग्रामर अधिक एयरक्राफ्ट जोड़ने में सक्षम होना चाहिए, हालांकि उन्हें एयरक्राफ्ट के प्रकारों के बारे में समान स्थिर विवरण बनाने के लिए लागू किया जाना चाहिए।

  • कुछ जीयूआई में, वहाँ उपयोगकर्ता (जैसे FriendlyName के रूप में विवरण के साथ) उपलब्ध प्रकार की सूची देख सकते हैं और जोड़ सकते हैं या विमान के उदाहरण निकाल देने के लिए एक तरह से किया जाना चाहिए, बचाया, मान लीजिए कि कुछ एक्सएमएल फ़ाइल के लिए, ।

तो, मूल रूप से, अगर मैं विरासत में मिला स्थिर सदस्यों और तरीकों को लागू करने के वर्गों को लागू कर सकता है, मैं विमान प्रकार लागू इस तरह के FriendlyName के रूप में स्थिर सदस्यों के लिए होगा। दुख की बात है कि मैं ऐसा नहीं कर सकता।

तो, इस परिदृश्य के लिए सबसे अच्छा डिज़ाइन क्या होगा?

+0

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

उत्तर

8

एक जवाब के साथ गुण (मेटाडाटा) प्रत्येक वर्ग को सजाने के लिए है:

[Description("Lockheed Martin F-16 Fighting Falcon")] 
public class F16 : Aircraft 
{ 
    // ... 
} 

यह System.ComponentModel में पहले से ही DescriptionAttribute उपयोग कर रहा है।

आप इस तरह मेटाडाटा प्राप्त कर सकते हैं:

Type t = typeof(F16); 
DescriptionAttribute attr = (DescriptionAttribute)Attribute.GetCustomAttribute(t, 
    typeof(DescriptionAttribute)); 
string description = (attr != null) ? attr.Description : t.Name; 

यह आपको F16 वर्ग के लिए एक संदर्भ से विवरण पाठ मिल जाएगा।

+0

नोट: यदि आप अपने आप को इस तरह की चीज अक्सर करते हैं, तो आप एक एक्सटेंशन विधि बना सकते हैं जो आपको 'टाइपऑफ (एफ 16) लिखने की अनुमति देगी। .GetDescription() '। – Aaronaught

+0

धन्यवाद, यह एक अच्छा तरीका है, लेकिन आप वास्तव में इसे लागू नहीं कर सकते हैं, क्या मैं सही हूँ? मेरा मतलब है, एक डेवलपर एक ऐसा विमान प्रकार बना सकता है जिसमें यह विशेषता न हो - और मैं वास्तव में इसे लागू करने का एक तरीका ढूंढना चाहता था। – yellowblood

+0

@yellowblood: हां, एक डेवलपर विशेषता के बिना एक प्रकार बना सकता है। यदि यह सैद्धांतिक रूप से अतिसंवेदनशील स्थैतिक तरीकों के लिए संभव था, तो एक डेवलपर भी एक खाली स्ट्रिंग या 'शून्य' वापस करने का विकल्प चुन सकता है या यहां तक ​​कि अपवाद भी फेंक सकता है। किसी भी तरह से, आप रक्षात्मक रूप से कोड करना चाहते हैं और अच्छे डिफ़ॉल्ट का उपयोग करना चाहते हैं - मेरे उदाहरण में यदि मैं विवरण उपलब्ध नहीं है तो मैंने कक्षा के नाम का उपयोग करने के लिए डिफ़ॉल्ट कर दिया है। मैं समझता हूं कि एक अर्थपूर्ण अंतर है, लेकिन दुर्भाग्य से आप गुणों को परिभाषित करने के लिए मजबूर नहीं कर सकते हैं। आप * क्या कर सकते हैं एक FxCop नियम बना सकते हैं जो लापता लोगों की पहचान करेगा। – Aaronaught

3

स्थिर तरीकों का उपयोग न करें। इसके बजाय उदाहरण विधियों का उपयोग करें।

इसके अलावा शीर्ष सार एक अमूर्त विधि का पर्दाफाश कर सकता है जो विमान विशिष्ट नाम वापस कर देगा।

public abstract class Aircraft 
{ 
    public abstract string Name { get; } 
    public abstract string FriendlyName { get; } 
} 
+1

आम तौर पर, हाँ, लेकिन वह अपने प्रश्न में उपयोग के मामले को स्पष्ट रूप से समझाता है - उसे वास्तव में पहले उन्हें बनाने के बिना उपलब्ध प्रकारों की एक सूची प्रदान करने में सक्षम होना चाहिए। प्लगइन की तरह आर्किटेक्चर में बहुत आम है। एक उदाहरण बनाना महंगा हो सकता है, और यदि 100 अलग-अलग प्रकार हैं, तो प्रत्येक के लिए विवरण प्राप्त करने के लिए उन्हें सभी को बनाने का अर्थ नहीं है। – Aaronaught

+0

@Aaronaught - सूची में वह आपके द्वारा सुझाए गए गुणों का उपयोग कर सकते हैं, और तत्काल - या तो कोड जनरेशन या हैशटेबल है जहां कुंजी = प्रकार और मान = कन्स्ट्रक्टर को प्रतिनिधि। प्रतिपादन प्रतिनिधि सस्ता तो प्रतिबिंब है। – Vitaly

+0

हारूनॉट (और मेन्डी और डेविड को उनके उत्तरों के लिए धन्यवाद) – yellowblood

4

आपको इन गुणों को स्थिर होने की आवश्यकता क्यों है?

public class Aircraft 
{ 
protected string AircraftName { get; protected set; } 
} 

public class F16 : Aircraft 
{ 
    public F16() 
    { 
    AircraftName="F16 Falcon"; 
    } 
} 
1

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

2

यह एक ऐसा मामला है जहां आप फैक्ट्री पैटर्न से लाभ उठा सकते हैं।विशिष्ट प्रकार के विमानों को आयात करने के बजाय, मानक IAircraftFactory इंटरफ़ेस प्रदान करें जो परिभाषित करता है कि प्रत्येक विमान फैक्ट्री को आपके लिए क्या करने की आवश्यकता है। यह वह जगह है जहां आप विवरण, यूआई सूचना आदि वापस कर सकते हैं। विमान फैक्ट्री तब विशेष विमान बनाने के लिए जिम्मेदार है। चूंकि आपके ग्राहकों को अपने विमान का पर्दाफाश करने के लिए एक कस्टम फैक्ट्री बनाना चाहिए, इसलिए उन्हें इंटरफेस को लागू करने और अपने सदस्यों के माध्यम से याद दिलाया जाता है कि उनके पास पूरा करने का अनुबंध है।

कुछ की तरह:

public interface IAircraft 
{ 
    //Aircraft instance details... 
} 

public interface IAircraftFactory 
{ 
    //Can include parameters if needed... 
    IAircraft BuildAircraft(); 

    //And other useful meta-data... 
    string GetDescription(); 
} 

//In some other Client-provided DLL... 
public class MyAircraftFactory : IAircraftFactory 
{ 
    IAircraft BuildAircraft() 
    { 
     return new MyAircraft(); 
    } 

    //... 
} 
+0

उत्तर के लिए धन्यवाद। हालांकि फैक्टरी पैटर्न मुझे उदाहरण के विवरण से मेटा-डेटा को विभाजित करने में मदद करेगा, फिर भी मेटा-डेटा को पढ़ने के लिए मुझे अभी भी एक उदाहरण (MyAircraftFactory) बनाना होगा। मान लीजिए कि मैं पहले से ही डीएलएल पढ़ने के लिए प्रतिबिंब का उपयोग कर रहा हूं, क्या मुझे इससे बचना नहीं चाहिए (प्रत्येक प्रकार के लिए एक उदाहरण बनाना)? – yellowblood

+0

यहां विचार यह है कि आप कभी भी प्रत्येक प्रकार के विमान के लिए एक फैक्टरी उदाहरण बनाते हैं। कारखाने को खोजने के लिए आपको केवल प्रतिबिंब का उपयोग करना होगा। संयोग से, यह एमईएफ जैसे विस्तार प्रणालियों के साथ बहुत स्वाभाविक रूप से फिट बैठता है, जहां आप एक विशिष्ट इंटरफेस के सभी कार्यान्वयन पा सकते हैं और उन्हें ऑटो-जादुई रूप से तुरंत चालू कर सकते हैं। –

+0

इस दृष्टिकोण का एक अन्य लाभ यह है कि आपके ग्राहकों के पास विमान की निर्माण प्रक्रिया पर अधिक नियंत्रण होता है, जिससे वे दृश्यों के पीछे चीजों को करने के लिए लचीलापन देते हैं, जैसे कि कैश उपप्रणाली जो कई विमान उपयोग करते हैं, स्थिर स्थिति पर भरोसा किए बिना। किसी भी साझा राज्य को कारखाने या उसके सदस्यों में अच्छी तरह से encapsulated किया जा सकता है। –

0

@Aaronaught प्लगइन की तरह वास्तुकला टिप्पणी के साथ सिर पर कील मारा।

पिछली बार जब मैंने इसका सामना किया, तो "डिस्क्रिप्टर" प्रकार होना था जो बनाने के लिए बहुत महंगा नहीं था, और एक उदाहरण क्षेत्र में मेटा डेटा को रखना था।

public class F16Descriptor : AircraftDescriptor 
{ 
    public override string Name { get { return "Lockheed Martin F-16 Fighting Falcon"; } } 
    public override Type AircraftType { get { return typeof(F16); } } 
} 

public class F16 : AircraftBase 
{ 
    ... 
} 
0

इस समस्या को हल करने के लिए एक दिलचस्प तरीका अलग कक्षाएं, जिसका उदाहरणों के रूप में कार्य प्रकार की के रूप में पहचान करने के लिए है कि विमान प्रकार भी डिजाइन में एक महत्वपूर्ण अवधारणा कर रहे हैं और बनाने के लिए उन्हें है एयरक्राफ्ट। इसे type object pattern (pdf) के रूप में जाना जाता है, और यह बहुत लचीली डिज़ाइनों की अनुमति देता है।

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