2010-07-15 9 views
8

क्या आप इस एक-लाइनर के डाउनसाइड्स को इस तथ्य के अलावा देख सकते हैं कि इसके कई उपयोग DRY सिद्धांत का उल्लंघन करेंगे? यह सीधा लगता है लेकिन तथ्य यह है कि मैंने दूसरों को प्रस्तावित नहीं देखा है, इससे मुझे आश्चर्य होता है कि इसमें कोई नकारात्मकता है या नहीं।एक लाइनर: वीक रेफरेंस-टू-ए-लैम्ब्डा इवेंट हैंडलर

कोड का यह बिट एक विधि में WeakReference बनाता है और उसके बाद एक ईवेंट हैंडलर पंजीकृत करता है जो संदर्भ के लक्ष्य को आमंत्रित करता है।

SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)(); 

धन्यवाद,
बेन

+0

क्या आपने मेरा प्रश्न/उत्तर [यहां] देखा था (http://stackoverflow.com/questions/1747235/weak-event-handler-model-for-use-with-lambdas)? यह एक लाइनर नहीं है, लेकिन मुझे लगता है * यह काम करता है ... – Benjol

उत्तर

11

मुझे नहीं लगता कि पैटर्न आप अपेक्षा करते हैं। क्या आप घटना को मौजूदा ऑब्जेक्ट का संदर्भ रखने से रोकने की कोशिश कर रहे हैं ताकि मेमोरी लीक को रोका जा सके? ProcessEvent का मूल्यांकन करने के लिए लैम्ब्डा अभिव्यक्ति this के मान को कैप्चर करेगी (माना जाता है कि ProcessEvent एक उदाहरण विधि है), इसलिए आपको अभी भी रिसाव होगा। यह कोड SomeEvent += (sender, e) => ProcessEvent(); करने जैसा ही है।

तुम कुछ इस तरह अधिक करने के लिए (जो भी आप क्या चाहते हैं नहीं है) की कोशिश कर रहा हो सकता है: तो तुम एक मजबूत संदर्भ की जरूरत नहीं होगी,

var reference = new WeakReference((Action)ProcessEvent); 
SomeEvent += (sender, e) => ((Action)reference.Target)(); 

अब लैम्ब्डा अभिव्यक्ति WeakReference कब्जा this पर। दुर्भाग्यवश, प्रोसेसएवेंट से बनाए गए प्रतिनिधि का संदर्भ कुछ और नहीं है, इसलिए अगली जीसी पर इसे हटा दिया जाएगा भले ही this अभी भी जिंदा है। (यह लक्ष्य शून्य के लिए भी जांच नहीं करता है)।

आप कुछ इस तरह की कोशिश कर सकते: इस तरह इसका इस्तेमाल

public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove) 
{ 
    var reference = new WeakReference(action.Target); 
    var method = action.Method; 
    EventHandler handler = null; 
    handler = delegate(object sender, EventArgs e) 
    { 
     var target = reference.Target; 
     if (target != null) 
     { 
      method.Invoke(target, null); 
     } 
     else 
     { 
      remove(handler); 
     } 
    }; 
    return handler; 
} 

और उसके बाद:

SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h); 

कि ProcessEvent के रिसीवर के लिए एक कमजोर संदर्भ रखेंगे, और स्वचालित रूप ईवेंट निकल जाएगा ईवेंट को इकट्ठा करने के बाद से हैंडलर, जो घटना को नियमित रूप से उठाए जाने तक स्मृति रिसाव को रोकना चाहिए।

+0

यह किसी भी घटना के लिए काम नहीं करता है। आपको * सटीक * ईवेंट के लिए इसे विशेषज्ञ बनाना होगा, उदाहरण के लिए, PropertiesChangedEventArgs और EventHandler के साथ EventChangedEventHandler के साथ EventArgs को प्रतिस्थापित करना। मैंने एक सामान्य संस्करण बनाने की कोशिश की जहां आप प्रकारों में गुजर सकते थे लेकिन यह काम नहीं कर रहा था। –

0

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

आप आमतौर पर रखरखाव के लिए एक ही पंक्ति में बहुत सी चीजें करने से बचना चाहते हैं।