2009-07-28 13 views
5

मैं एक .NET वेब एप्लिकेशन लिख रहा हूं जिसमें प्रशासक अपने उपयोगकर्ताओं को प्रस्तुत विभिन्न डेटा प्रविष्टि फ़ॉर्म को कस्टमाइज़ कर सकते हैं। लगभग आधे दर्जन विभिन्न फ़ील्ड प्रकार हैं जो व्यवस्थापक बना सकते हैं और अनुकूलित कर सकते हैं (यानी टेक्स्ट, न्यूमेरिक, ड्रॉपडाउन, फ़ाइल अपलोड)। सभी फ़ील्ड बेस विशेषताओं/व्यवहारों का एक सेट साझा करते हैं (क्या फ़ील्ड आवश्यक है? क्या इसमें डिफ़ॉल्ट फ़ील्ड मान होगा?)। फील्ड विशिष्ट विशेषताओं/व्यवहारों की एक श्रृंखला भी है (यानी ड्रॉपडाउन में डेटा स्रोत विशेषता है, लेकिन टेक्स्ट फ़ील्ड नहीं है)। मैं सादगी के लिए समस्या डोमेन की कई अन्य विशेषताओं को छोड़ रहा हूं।विधि ओवरलोडिंग और पॉलिमॉर्फिज्म

कक्षा पदानुक्रम सरल है: एक अमूर्त सुपरक्लास जो सामान्य व्यवहार/विशेषताओं को घेरता है और लगभग आधे दर्जन ठोस उपखंड जो क्षेत्र विशिष्ट सामग्री से निपटते हैं।

प्रत्येक फ़ील्ड प्रकार को एक विशिष्ट प्रकार के .NET सर्वर नियंत्रण के रूप में प्रस्तुत किया जाता है (यानी मैप किया गया), जिनमें से सभी System.Web.UI.Control से प्राप्त होते हैं।

मैं क्षेत्र डोमेन वस्तुओं और उनकी इसी UI नियंत्रण के बीच मान मैप करने के लिए निम्न कोड बनाया:

public static void Bind(Control control, IList<DocumentFieldBase> fieldBaseList) 

    foreach (DocumentFieldBase fieldBase in fields){ 

      if (typeof (DocumentFieldText).IsInstanceOfType(fieldBase)){ 
       TextBox textbox = (TextBox) control; 
       textbox.Text = (fieldBase as DocumentFieldText).GetValue(); 
      } 

      if (typeof (DocumentFieldDropDown).IsInstanceOfType(fieldBase)){ 
       DropDown dropDown= (DropDown) control; 
       dropDown.Text = (fieldBase as DocumentFieldSelectOne).GetValue().Text; 
       dropDown.DataSource= (fieldBase as DocumentFieldSelectOne).DataSource; 
       dropDown.Id= (fieldBase as DocumentFieldSelectOne).GetValue().Id; 
      } 

      //more if statements left out for brevity 
     } 
} 

मैं उन बयानों उस प्रकार की जाँच प्रदर्शन करता है, तो धर्मभ्रष्ट खाई करने के लिए चाहते हैं। जिस दृष्टिकोण के लिए मैं शूटिंग कर रहा था वह सबक्लास टाइपिंग का उपयोग करके क्षेत्र/नियंत्रण के प्रत्येक संयोजन के लिए एक विधि ओवरलोड बनाना था। उदाहरण के लिए:

public static void Bind(TextBox control, DocumentFieldText fieldText){ 
//some implementation code 
} 
public static void Bind(DropDown control, DocumentFieldDropDown fieldDropDown){ 
//some implementation code 
} 

मुझे उम्मीद थी कि मैं तो क्रम पर उचित अधिभार कॉल करने के लिए विशिष्ट उपवर्ग का उपयोग कर नेट पर भरोसा कर सकता है इस्तेमाल किया जा रहा: उदाहरण के लिए:

foreach (DocumentFieldBase field in fields){ 
    Control control = FindControl(field.Identifier); 
    Bind(control, field) 
} 

दुर्भाग्य से, जब मैं इसे आज़माता हूं तो संकलक चॉक: तर्क '1': 'System.Web.UI.Control' से 'टेक्स्टबॉक्स' में परिवर्तित नहीं हो सकता है।

यदि मुझे टेक्स्टबॉक्स में पहला तर्क डालना है, तो मैं अपने आप को जांचने के लिए वापस आ रहा हूं और इस अभ्यास के पूरे उद्देश्य को हरा देता हूं।

क्या मैं एक प्राप्त करने की कोशिश कर रहा हूं) संभव है और बी) एक अच्छा विचार?

उत्तर

5

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

विज़िटर पैटर्न का उपयोग अक्सर इसके आसपास काम करने के लिए किया जा सकता है। विचार यह है कि आप DocumentFieldBase एक विधि (जिसे आप कंक्रीट सबक्लास में ओवरराइड करते हैं) देते हैं जो Control (कंक्रीट सबक्लास में भी ओवरराइड) पर एक विधि कहता है जो वास्तविक कार्य करता है।

दुर्भाग्यवश, Control वर्ग का स्रोत कोड शायद आपके नियंत्रण में नहीं है * ... इसलिए आपको एक और अधिक हैकिश समाधान का सहारा लेना होगा। this question का स्वीकृत उत्तर प्रतिबिंब का उपयोग करने वाला एक प्रदान करता है।

* विस्तार विधियां स्थिर तरीकों के लिए सिंटैक्टिक चीनी हैं, और इस प्रकार संकलन समय और इस परिदृश्य में कोई उपयोग नहीं किया जाता है।

+0

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

6

सी # 4 से पहले, सभी अधिभार संकलन समय पर किया जाता है। आपको निष्पादन समय पर प्रभावी ढंग से ओवरलोड करने के लिए डबल प्रेषण या विज़िटर पैटर्न का उपयोग करना होगा, और यह जल्दी से गन्दा हो जाता है।

सी # 4 में, आप एक चर के रूप में गतिशील की घोषणा कर सकता है और जाने यह सब निष्पादन समय पर हल हो:

foreach (DocumentFieldBase field in fields){ 
    dynamic control = FindControl(field.Identifier); 
    Bind(control, field) 
} 

जाहिर है कि इस समय ज्यादा मदद नहीं है, हालांकि (जब तक आप VS2010b1 उपयोग कर रहे हैं) ।

एक विकल्प Action<object> को Type से नक्शे का उपयोग करने के लिए है, लेकिन फिर आप विरासत मुद्दों मिलता है ... (आप संभावित कंक्रीट से प्रकार पदानुक्रम ऊपर काम कर रखने के जब तक आप में एक प्रविष्टि पाया आपत्ति करने के लिए टाइप करने के लिए होगा नक्शा)। आपको अभी भी कार्रवाई के भीतर सही प्रकार पर डालने की आवश्यकता होगी :(

0

क्या आपके पास दस्तावेज़ फ़ील्डबेस में एक सार, गैर-स्थैतिक Bind() विधि नहीं हो सकती है, फिर प्रत्येक ठोस वर्ग के कार्यान्वयन के अंदर डाउनकास्टिंग करें? प्रत्येक DocumentFieldBase कक्षा जानता है कि Control किस प्रकार का हो रहा है, है ना?

+0

कार्ल, मैंने इस दृष्टिकोण पर विचार नहीं किया। मैं अपने डोमेन परत में System.Web.UI पर निर्भरता पेश करने के लिए बहुत उत्सुक नहीं हूं, लेकिन मैं एक त्वरित पीओसी लिख सकता हूं। धन्यवाद! –

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