2009-01-12 12 views
8

मैं एक आम समस्या क्या होनी चाहिए में आया है। जब मेरे पास एक ऐसी घटना होती है जिसे कई अलग-अलग वर्गों द्वारा सब्सक्राइब किया जा सकता है, तो इन कक्षाओं में से एक द्वारा फेंक दिया गया अपवाद कॉलबैक श्रृंखला को मार देगा; क्योंकि मुझे कॉलबैक के आदेश में प्राथमिकता नहीं है, इसके परिणामस्वरूप कुछ वर्गों के लिए अप्रत्याशित राज्य परिवर्तन हो सकते हैं, न कि दूसरों के लिए।मैं अपनी प्रतिनिधि श्रृंखला को कचरा करने वाले अपवादों को कैसे रोकूं?

बाइबल में (CLR via C#, मैं सी # 2.0 का उपयोग कर रहा हूं) इसके आसपास पाने के लिए MulticastDelegate.GetInvocationList का उपयोग करने के बारे में एक छोटा अनुच्छेद है, लेकिन कुछ भी नहीं। तो मेरा सवाल है: इससे निपटने का सबसे अच्छा तरीका क्या है? क्या मुझे हर बार MulticastDelegate.GetInvocationList का उपयोग करना पड़ता है ?? या क्या मुझे किसी भी प्रकार की रोलबैक तंत्र में प्रतिनिधि श्रृंखला के हिस्से के रूप में बुलाए जाने वाले सभी तरीकों को संलग्न करने की आवश्यकता है? सरल घटना/प्रतिनिधि मॉडल की तुलना में ये सभी विकल्प इतने जटिल क्यों हैं जो सी # में उपयोग करना इतना आसान है? और भ्रष्ट राज्य के समाप्त होने के बिना मैं सरल तरीके का उपयोग कैसे कर सकता हूं?

धन्यवाद!

+0

अपनी टिप्पणी –

उत्तर

11

यदि आप बस एक प्रतिनिधि को आमंत्रित करते हैं, तो यह सभी लक्ष्य विधियों को क्रम में कॉल करेगा। आप GetInvocationList उपयोग करने के लिए यदि आप उन्हें व्यक्तिगत रूप से निष्पादित करने के लिए चाहते हैं की जरूरत है - उदाहरण के लिए: एक व्यक्ति लक्ष्य की विफलता के बाद जारी रखने के लिए प्रत्येक

  • की वापसी मूल्य पर कब्जा करने के

    • प्रत्येक
    • के बाद Cancel जाँच करने के लिए

    इसका उपयोग करने का सबसे अच्छा तरीका है: आप इसे कैसे व्यवहार करना चाहते हैं? यह मेरे लिए स्पष्ट नहीं है ... उदाहरण के लिए, इस एक विस्तार विधि काफी अच्छी तरह से सूट हो सकता है:

    static void InvokeIgnoreErrors(this EventHandler handler, 
         object sender) { 
        if(handler != null) { 
         foreach(EventHandler subHandler in handler.GetInvocationList()) { 
          subHandler(sender, EventArgs.Empty); 
         } 
        } 
    } 
    

    तो फिर तुम सिर्फ myHandler.InvokeIgnoreErrors(this); (उदाहरण के लिए) कह सकते हैं।

    एक और उदाहरण हो सकता है:

    static bool InvokeCheckCancel(this CancelEventHandler handler, 
         object sender) { 
        if(handler != null) { 
         CancelEventArgs args = new CancelEventArgs(false); 
         foreach(CancelEventHandler subHandler in handler.GetInvocationList()) { 
          subHandler(sender, args); 
          if(args.Cancel) return true; 
         } 
        } 
        return false; 
    } 
    

    जो पहली घटना के बाद बंद हो जाता है रद्द करने का अनुरोध करता है।

  • +0

    ठीक उत्तर दें, यह विस्तार विधियों के लिए एक अच्छा उपयोग है। दुर्भाग्यवश मैं सी # 2.0 में फंस गया हूं - कोई विचार है कि मैं इसे यहां कैसे कर सकता हूं? धन्यवाद! –

    +1

    बस एक स्थिर विधि का उपयोग करें। "यह" निकालें, और बस YourUtilityClass.InvokeIgnoreErrors (myHandler, this) का उपयोग करें; –

    1

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

    +0

    'प्रचार' से आपका क्या मतलब है? मुझे स्पष्ट रूप से मेरी प्रतिनिधि श्रृंखला में विधि # 3 की आवश्यकता हो सकती है ताकि यह सूचित किया जा सके कि यह क्रैश हो गया है, क्योंकि मुझे विधियों # 1 और # 2 में किए गए किसी भी बदलाव को वापस रोल करना होगा (लेकिन विधि # 4 नहीं)। –

    +0

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

    +0

    ने कहा कि निश्चित रूप से ऐसे मामले हैं जहां आप सीधे प्रतिनिधि को सीधे आमंत्रित करने के बजाय आमंत्रण सूची का उपयोग करना चाहते हैं क्योंकि मार्क ने वर्णित किया है। –

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

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