2010-11-20 22 views
5

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

उदाहरण:

संपादित करें: के रूप में Lucerno

public class ObjectManipulator 
{ 
    private void DoX(object o) { } 
    private void DoY(object o) { } 
    private void DoZ(object o) { } 

    public void DoAction(string action, object o) 
    { 
     switch (action) 
     { 
      case "DoX": 
       DoX(o); 
       break; 
      case "DoY": 
       DoY(o); 
       break; 
      case "DoZ": 
       DoZ(o); 
       break; 
      default: 
       throw new Exception(string.Format(
        "Cannot locate action:{0}", action)); 
     } 
    } 

    public void DoActionViaReflection(string action, object o) 
    { 
     MethodInfo method = typeof(ObjectManipulator). 
      GetMethod(action, new Type[] { typeof(object) }); 
     if (method == null) 
     { 
      throw new Exception(string.Format(
       "Cannot locate action:{0}", action)); 
     } 
     else 
     { 
      method.Invoke(this, new object[] { o }); 
     } 
    } 
    private Dictionary<string, Action<object>> _methods; 
    public ObjectManipulator() 
    { 
     _methods = new Dictionary<string, Action<object>>() 
     { 
      {"DoX", o => DoX(o)}, 
      {"DoY", o => DoY(o)}, 
      {"DoZ", o => DoZ(o)} 
     }; 
    } 
    public void DoActionViaDelegates(string action, object o) 
    { 
     if (!_methods.ContainsKey(action)) 
     { 
      throw new Exception(string.Format(
       "Cannot locate action:{0}", action)); 
     } 
     else 
     { 
      _methods[action](o); 
     } 
    } 

} 

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

क्या एक विधि अन्य महत्वपूर्ण रूप से बेहतर प्रदर्शन करेगी?

क्या प्रदर्शन में परिवर्तन होगा यदि केवल 3 की बजाय 100 अलग-अलग कार्रवाइयां होंगी?

यदि आप इसे पढ़ रहे थे तो आप अपने कोड में क्या देखते हैं?

+0

यह अनिवार्य बनाम घोषणात्मक प्रोग्रामिंग शैली के बारे में काफी सवाल है। किर्क बाद में पसंद करते हैं, जबकि मैं बाद में पसंद करता हूं, जैसा कि आप मेरे उत्तर से देख सकते हैं। यह स्पष्ट करने के लिए, "दाएं" या "गलत" भी नहीं है। – Lucero

उत्तर

3

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

मेरा सामान्य दृष्टिकोण खोज समय के दौरान ऐसे पैटर्न को लागू करने के लिए प्रतिबिंब का उपयोग करना है, लेकिन आमंत्रण समय पर प्रतिनिधियों का उपयोग करना है। इससे आपको प्रारंभिक बाध्य दृष्टिकोण के बहुत करीब प्रदर्शन के साथ प्रतिबिंब दृष्टिकोण की लचीलापन मिलती है।

  • डिस्कवरी चरण: उपयोग प्रतिबिंब सदस्यों (गुण, इंटरफेस, हस्ताक्षर का उपयोग करके कोडिंग सम्मेलनों, और/या) खोजने के लिए। आपके मामले में आपके पास हमेशा एक ही हस्ताक्षर होता है, इसलिए उपयोग करने के लिए प्रतिनिधि Action<object> होगा। CreateDelegate() का उपयोग करके MethodInfo से एक प्रतिनिधि बनाकर, उन सदस्यों को Dictionary<string, Action<object>> उदाहरण में जोड़ें।

  • प्रार्थना किए चरण: उसके प्रमुख के माध्यम से प्रतिनिधि मिलता है और यह आह्वान है, जो बहुत सरल है (यहाँ यह सोचते शब्दकोश methods कहा जाता है): आपकी चिंता methods[action](o)

2

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

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

+0

'MethodInfo' पर गतिशील आमंत्रण धीमा है, इसलिए यह सबसे बड़ा प्रदर्शन हिट होगा। – Lucero

+0

@ लुसेरो, यकीन है, यह धीमा है। सवाल यह है कि क्या यह महत्वपूर्ण है। मेरे अनुभव में, यह बहुत ही कम करता है। –

2

प्रतिनिधियों का उपयोग करने के बारे में कैसे?आप ऐसा ही कुछ इस्तेमाल कर सकते हैं:

var Actions = new Dictionary<String, Action<object>>(); 
Actions["DoX"] = x => DoX(x); 
Actions["DoY"] = x => DoY(x); 
Actions["DoZ"] = x => DoZ(x); 

और बाद में

public void DoAction(string action, object o) 
{ 
    Actions[action](o); 
} 

मैं को बेहतर प्रदर्शन करने, अगर आप कई मामलों है, क्योंकि शब्दकोश एक हैश देखने है लगता है।

प्रतिबिंब के प्रकार आप, सुरक्षा के मुद्दों बना सकते हैं उपयोगकर्ता किसी अन्य समारोह के नाम पर दे सकते हैं अगर इस्तेमाल किया

+0

मुझे संदेह है कि यह संकलित करेगा, इस तथ्य को देखते हुए कि 'डीओएक्स',' डीओवाई 'और' डीओजेड 'कार्य नहीं हैं, लेकिन लैम्ब्डा वापसी मूल्य की अपेक्षा करता है। – Lucero

+0

ठीक है इसे ठीक किया गया है, "कार्रवाई" किसी प्रतिनिधि के लिए सही प्रकार है बिना किसी वापसी मूल्य के – user287107

2

आप @ user287107 के जवाब thusly ठीक कर सकते हैं:

var Actions = new Dictionary<String, Action<object>>(); 
Actions["DoX"] = DoX; 
Actions["DoY"] = DoY; 
Actions["DoZ"] = DoZ; 

इस आशय में खोज कर रहा है @ लुसेरो के उत्तर का चरण स्पष्ट रूप से, जो उपयोगी हो सकता है यदि नाम हमेशा मेल नहीं खाते हैं।

एक enum में क्रियाओं के सेट को परिभाषित करना भी संभव होगा यदि यह संभव हो तो अच्छा होगा - यह थोड़ा तेज़ होगा क्योंकि आपको स्ट्रिंग को हश करने की आवश्यकता नहीं होगी। यह सुनिश्चित करने के लिए कि आप किसी भी संभावित मूल्य को याद नहीं करते हैं, यह आपको यूनिट परीक्षण लिखने में सक्षम बनाता है।

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