2008-09-25 13 views
148

क्या यह बताने का कोई तरीका है कि कोई ऑब्जेक्ट हैंडलर किसी ऑब्जेक्ट में जोड़ा गया है या नहीं? मैं ऑब्जेक्ट्स की सूची को सत्र स्थिति में/बाहर क्रमबद्ध कर रहा हूं ताकि हम एसक्यूएल आधारित सत्र स्थिति का उपयोग कर सकें ... जब सूची में किसी ऑब्जेक्ट में एक संपत्ति बदल जाती है तो इसे ध्वजांकित करने की आवश्यकता होती है, जिसे ईवेंट हैंडलर ने ठीक से पहले देखभाल की । हालांकि अब जब वस्तुएं deserialized हैं यह घटना हैंडलर नहीं मिल रहा है।क्या कोई इवेंट हैंडलर पहले ही जोड़ा जा चुका है?

हल्के परेशानियों के एक फिट में, मैंने अभी ईवेंट प्राप्त करने के लिए इवेंट हैंडलर जोड़ा है जो ऑब्जेक्ट तक पहुंचता है। इसे अब बुलाया जा रहा है जो कि महान है, सिवाय इसके कि इसे 5 गुना की तरह बुलाया जा रहा है, इसलिए मुझे लगता है कि जब भी वस्तु का उपयोग किया जाता है तो हैंडलर बस जोड़ता रहता है।

यह केवल अनदेखा करने के लिए पर्याप्त सुरक्षित है, लेकिन मैं यह देखने के लिए इतना साफ कर दूंगा कि हैंडलर पहले ही जोड़ा जा चुका है, इसलिए मैं केवल एक बार ऐसा करता हूं।

क्या यह संभव है?

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

+0

यह भी देखना http://stackoverflow.com/questions/367523/कैसे-से-सुनिश्चित-एक-ईवेंट-केवल-सब्सक्राइब किया गया-एक बार –

उत्तर

107

को परिभाषित वर्ग बाहर से, के रूप में @Telos का उल्लेख है, आप केवल eventhandler एक += या एक -= के बाएं हाथ की ओर पर उपयोग कर सकते हैं। इसलिए, यदि आपके पास परिभाषित कक्षा को संशोधित करने की क्षमता है, तो आप यह जांच कर जांच कर सकते हैं कि ईवेंट हैंडलर null है - यदि ऐसा है, तो कोई ईवेंट हैंडलर जोड़ा नहीं गया है। यदि नहीं, तो हो सकता है कि आप Delegate.GetInvocationList में मानों के माध्यम से लूप कर सकें। यदि कोई उस प्रतिनिधि के बराबर है जिसे आप ईवेंट हैंडलर के रूप में जोड़ना चाहते हैं, तो आप जानते हैं कि यह वहां है।

public bool IsEventHandlerRegistered(Delegate prospectiveHandler) 
{ 
    if (this.EventHandler != null) 
    { 
     foreach (Delegate existingHandler in this.EventHandler.GetInvocationList()) 
     { 
      if (existingHandler == prospectiveHandler) 
      { 
       return true; 
      } 
     } 
    } 
    return false; 
} 

और इसे आसानी से संशोधित किया जा सकता है "यदि वहां नहीं है तो हैंडलर जोड़ें"। यदि आपके पास ईवेंट को उजागर करने वाले वर्ग के अंदरूनी हिस्से तक पहुंच नहीं है, तो आपको @Lou Franco द्वारा सुझाए गए अनुसार -= और += का पता लगाना होगा।

हालांकि, आप इस ऑब्जेक्ट को स्वयं ट्रैक करने का कोई तरीका नहीं ढूंढ सकते हैं, यह देखने के लिए कि आप कमीशनिंग और इन ऑब्जेक्ट्स को डिमोकिशन कर रहे हैं, फिर से आप बेहतर तरीके से दोबारा बेहतर हो सकते हैं।

+7

यह संकलित नहीं करता है, EventHandler केवल + = या - = के बाईं ओर हो सकता है। – CodeRedick

+0

आह हाँ। अच्छी बात। शामिल। –

+2

आगे स्पष्टीकरण पर वोट हटा दिया गया। एसक्यूएल राज्य पूरे विचार को बहुत अधिक नष्ट कर रहा है ... :( – CodeRedick

18

यदि यह एकमात्र हैंडलर है, तो आप यह देखने के लिए जांच सकते हैं कि ईवेंट शून्य है, अगर ऐसा नहीं है, हैंडलर जोड़ा गया है।

मुझे लगता है कि आप अपने हैंडलर के साथ ईवेंट पर सुरक्षित रूप से कॉल कर सकते हैं - भले ही इसे जोड़ा नहीं गया हो (यदि नहीं, तो आप इसे पकड़ सकते हैं) - यह सुनिश्चित करने के लिए कि यह जोड़ने से पहले वहां नहीं है।

+2

जैसे ही ईवेंट कहीं और संभाला जाता है, यह तर्क टूट जाएगा। – bugged87

0
EventHandler.GetInvocationList().Length > 0 
+2

यह फेंक नहीं देता है जब सूची == शून्य? इवेंट हैंडलर के मालिक के बाहर –

+2

आप केवल = = और + = का उपयोग कर सकते हैं। आप घटना तक नहीं पहुंच सकते हैं। – tbergelt

6

यह उदाहरण दिखाता है कि जोड़े गए सभी हैंडलरों को प्रतिनिधियों को पुनर्प्राप्त करने के लिए GetInvocationList() विधि का उपयोग कैसे करें। यदि आप यह देखने के लिए देख रहे हैं कि कोई विशिष्ट हैंडलर (फ़ंक्शन) जोड़ा गया है तो आप सरणी का उपयोग कर सकते हैं।

public class MyClass 
{ 
    event Action MyEvent; 
} 

... 

MyClass myClass = new MyClass(); 
myClass.MyEvent += SomeFunction; 

... 

Action[] handlers = myClass.MyEvent.GetInvocationList(); //this will be an array of 1 in this example 

Console.WriteLine(handlers[0].Method.Name);//prints the name of the method 

आप अगर एक विशेष समारोह जोड़ दिया गया है को देखने के लिए प्रतिनिधि की विधि संपत्ति पर विभिन्न गुणों की जांच कर सकते हैं।

यदि आप यह देखने के लिए देख रहे हैं कि केवल एक संलग्न है, तो आप केवल शून्य के लिए परीक्षण कर सकते हैं।

+0

GetInvocationList() मेरी कक्षा का सदस्य नहीं है। असल में, मुझे इस विधि को किसी ऑब्जेक्ट या हैंडलर पर नहीं मिल रहा है, जिस पर मुझे पहुंच है ... – CodeRedick

+0

मैंने कोड तय किया। यह प्रश्न में घटना का सदस्य है। –

+0

मैंने यह भी कोशिश की थी, जाहिर है कि आप केवल कक्षा के अंदर से इस तरह की घटना तक पहुंच सकते हैं। मैं इसे सामान्य रूप से कर रहा हूं, और जैसा कि अन्य ने उल्लेख किया है कि ईवेंट हैंडलर शायद वैसे भी खो रहे हैं। स्पष्टीकरण के लिए धन्यवाद! – CodeRedick

4

यदि मैं आपकी समस्या को सही ढंग से समझता हूं तो आपको बड़ी समस्याएं हो सकती हैं। आपने कहा कि अन्य वस्तुएं इन घटनाओं की सदस्यता ले सकती हैं। जब ऑब्जेक्ट को अन्य ऑब्जेक्ट्स को क्रमबद्ध और deserialized किया जाता है (जिनके बारे में आप पर नियंत्रण नहीं है) उनके ईवेंट हैंडलर खो देंगे।

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

+1

डी ओह! इस बारे में भी सोचा नहीं था ... हालांकि यह स्पष्ट होना चाहिए था कि मेरी मूल समस्या पर विचार करना मेरा खुद का हैंडलर खो रहा था। – CodeRedick

141

मैं हाल ही में इसी तरह की स्थिति में आया जहां मुझे केवल एक बार एक कार्यक्रम के लिए हैंडलर पंजीकृत करने की आवश्यकता थी। मैंने पाया है कि आप सुरक्षित रूप से पहले अपंजीकृत कर सकते हैं, और तब पुन रजिस्टर, भले ही हैंडलर सब पर पंजीकृत नहीं है:

myClass.MyEvent -= MyHandler; 
myClass.MyEvent += MyHandler; 

ध्यान दें कि यह हर बार जब आप अपने हैंडलर रजिस्टर कर सुनिश्चित करेगा कि आपके हैंडलर केवल एक बार पंजीकृत है । मैं Alf के जवाब से सहमत मेरे लिए :)

+5

जोखिम भरा लगता है; यदि हैंडलर को हटाने और इसे वापस जोड़ने से पहले एक घटना निकाल दी जाती है, तो इसे याद किया जाएगा। – Jimmy

+18

निश्चित रूप से। आपका मतलब है कि यह धागा सुरक्षित नहीं है। लेकिन यह कई धागे या जैसे चलने पर केवल एक समस्या हो सकती है, जो सामान्य नहीं है। ज्यादातर मामलों में सादगी के लिए यह पर्याप्त होना चाहिए। – alf

+0

मुझे लगता है कि यह करने का यह सबसे अच्छा तरीका है जब भी आप इसे घटाते हैं, वैसे भी अभ्यास करें, फिर भी आप सुरक्षित हो सकते हैं। अन्यथा आप यह पता लगाकर दीवार पर अपने सिर पर हमला कर रहे होंगे कि उसी विधि को दो बार –

0

एक बहुत अच्छा अभ्यास की तरह लगता है, लेकिन छोटे संशोधन यह है ,, उपयोग करने के लिए,

  try 
      { 
       control_name.Click -= event_Click; 
       main_browser.Document.Click += Document_Click; 
      } 
      catch(Exception exce) 
      { 
       main_browser.Document.Click += Document_Click; 
      } 
संबंधित मुद्दे