दिलचस्प पोस्ट
एक शब्दकोश ऑब्जेक्ट जो चाबियों के लिए मानों की श्रेणी का उपयोग करता है PHP दिनांकटाइम :: महीनों को जोड़ने और घटाना संशोधित करें सूची और सरणी के बीच का अंतर MySQL – AUTO_INCREMENT होने के लिए एक कॉलम बदलें जावा में सरणी की शुरुआत में मैं कैसे नया सरणी तत्व जोड़ सकता हूं? एक गुमनाम आंतरिक वर्ग से बाहरी वर्ग के लिए खोजशब्द ओरेकल में मौजूदा सारणी के लिए एक स्वत: वेतन वृद्धि प्राथमिक कुंजी जोड़ें WPF एसवीजी फ़ाइलों को WPF में चिह्न के रूप में उपयोग करने का सही तरीका क्या है समानताएं के साथ एक क्षेत्र बनाएँ कैसे Xcode के लिए पीजेएसआईपी बनाने और संकलन, नमूना कोड IPJSUA का प्रयोग करने के लिए? Entity Framework मॉडल के साथ परियोजना के लिए विभिन्न परियोजनाओं में POCO कक्षाएं उत्पन्न करें Const तर्कों और ओवरलोडिंग के साथ कार्य आईसीएस में TYPE_SYSTEM_OVERLAY दृश्य सी # विंडो फॉर्म के लिए पारदर्शिता के माध्यम से क्लिक करें? सीएसएस पहचानकर्ताओं के लिए अनुमत वर्ण

क्या जोश स्मिथ ने रिले कॉमांड का कार्यान्वयन दोषपूर्ण है?

मॉडल-व्यू-देखें मॉडल डिजाइन पैटर्न के साथ जोश स्मिथ के लेख WPF Apps संदर्भ पर विचार करें, विशेष रूप से RelayCommand के उदाहरण कार्यान्वयन (चित्रा 3) में। (इस प्रश्न के लिए पूरे लेख के माध्यम से पढ़ने की आवश्यकता नहीं है।)

सामान्य तौर पर, मुझे लगता है कि कार्यान्वयन उत्कृष्ट है, लेकिन मुझे CommandManager की RequerySuggested घटना के लिए CanExecuteChanged सदस्यता के प्रतिनिधिमंडल के बारे में एक सवाल है। RequerySuggested राज्यों के लिए दस्तावेज :

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

फिर भी RelayCommand का नमूना कार्यान्वयन इस तरह के सदस्य हैंडलर को नहीं बनाए रखता है:

 public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } 
  1. क्या यह RelayCommand के क्लाइंट तक कमजोर संदर्भ रिसाव करता है, इस बात की आवश्यकता होती है कि RelayCommand के उपयोगकर्ता RelayCommand के कार्यान्वयन को समझते हैं और खुद को लाइव संदर्भ बनाए रखते हैं?
  2. यदि हां, तो क्या इसका अर्थ है, उदाहरण के लिए, RelayCommand के कार्यान्वयन को संशोधित करें, जैसा कि RelayCommand ग्राहक की संभावित समयपूर्व जीसी को कम करने के लिए निम्नलिखित जैसा कुछ है:

     // This event never actually fires. It's purely lifetime mgm't. private event EventHandler canExecChangedRef; public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; this.canExecChangedRef += value; } remove { this.canExecChangedRef -= value; CommandManager.RequerySuggested -= value; } } 

वेब के समाधान से एकत्रित समाधान "क्या जोश स्मिथ ने रिले कॉमांड का कार्यान्वयन दोषपूर्ण है?"

मुझे भी विश्वास है कि यह कार्यान्वयन दोषपूर्ण है , क्योंकि यह निश्चित रूप से ईवेंट हैंडलर के कमजोर संदर्भ को लीक करता है। यह वास्तव में बहुत बुरा है
मैं RelayCommand लाइट टूलकिट और उसमें लागू RelayCommand का उपयोग कर रहा हूं और यह लेख में ही लागू किया गया है।
निम्न कोड OnCanExecuteEditChanged कभी नहीं OnCanExecuteEditChanged :

 private static void OnCommandEditChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var @this = d as MyViewBase; if (@this == null) { return; } var oldCommand = e.OldValue as ICommand; if (oldCommand != null) { oldCommand.CanExecuteChanged -= @this.OnCanExecuteEditChanged; } var newCommand = e.NewValue as ICommand; if (newCommand != null) { newCommand.CanExecuteChanged += @this.OnCanExecuteEditChanged; } } 

हालांकि, अगर मैं इसे इस तरह बदलता हूं, तो यह काम करेगा:

 private static EventHandler _eventHandler; private static void OnCommandEditChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var @this = d as MyViewBase; if (@this == null) { return; } if (_eventHandler == null) _eventHandler = new EventHandler(@this.OnCanExecuteEditChanged); var oldCommand = e.OldValue as ICommand; if (oldCommand != null) { oldCommand.CanExecuteChanged -= _eventHandler; } var newCommand = e.NewValue as ICommand; if (newCommand != null) { newCommand.CanExecuteChanged += _eventHandler; } } 

एकमात्र अंतर? जैसा कि CommandManager.RequerySuggested के दस्तावेज में CommandManager.RequerySuggested गया है। CommandManager.RequerySuggested मैं एक क्षेत्र में ईवेंट हैंडलर को सहेज रहा हूं।

मुझे उनके " अंडरस्टँडिंग रूटेड कमांड्स " लेख पर जोश की टिप्पणी में जवाब मिला है:

[…] आप अपने CanExecuteChanged घटना में WeakEvent पैटर्न का उपयोग करना होगा। इसका कारण यह है कि दृश्य तत्व उस घटना को हुकूमत करेंगे, और जब से ऐप बंद हो जाने तक कमान ऑब्जेक्ट कचरा एकत्रित नहीं हो सकता, तब तक मेमोरी रिसाव के लिए एक बहुत ही वास्तविक क्षमता है। […]

बहस यह है कि CanExecuteChanged कार्यान्वयनकर्ताओं को केवल पंजीकृत हैंडलर को कमजोर रूप से पकड़ना चाहिए, क्योंकि WPF विज़ुअल्स स्वयं को खोलना बेवकूफ़ हैं यह सबसे आसानी से CommandManager को CommandManager द्वारा कार्यान्वित किया CommandManager , जो पहले से यह करता है। संभवतः एक ही कारण के लिए

खैर, परावर्तक के अनुसार, यह RoutedCommand क्लास में उसी तरह लागू किया गया है, इसलिए मुझे लगता है कि यह ठीक होना चाहिए … जब तक कि WPF टीम में किसी ने गलती नहीं की;)

मेरा मानना ​​है कि यह दोषपूर्ण है।

कमांडमैनेजर को घटनाओं को दोबारा आरम्भ करके, आप निम्न व्यवहार प्राप्त करते हैं

यह सुनिश्चित करता है कि WPF कमांडिंग इंफ्रास्ट्रक्चर सभी रिले कॉमांड ऑब्जेक्ट्स को पूछता है, जब भी वे आंतरिक-इन आदेशों को पूछते हैं, तब भी निष्पादित कर सकते हैं।

हालांकि, क्या होता है जब आप सभी नियंत्रणों को एक एकल आदेश में बांटना चाहते हैं जो कि CanExecute स्थिति का पुनः मूल्यांकन कर सकता है? अपने कार्यान्वयन में, आपको कमान मैनेजर के पास जाना चाहिए, जिसका अर्थ है

आपके आवेदन में बाध्य करने वाली हर एक कमांड को पुनः मूल्यांकन किया जाता है

इसमें उन सभी लोगों को शामिल किया गया है जो बीन्स की किसी पहाड़ी की कोई बात नहीं करते हैं, जिनके मूल्यांकन में कैनक्सक्च्यूटे के दुष्प्रभाव (जैसे कि डेटाबेस पहुंच या लंबे समय से चलने वाले कार्य) हैं, जो कि एकत्र किए जाने की प्रतीक्षा कर रहे हैं … इसकी तरह एक स्लेजहेमर एक फ्रिगेंस कील चलाने के लिए

आपको ऐसा करने के असर पर गंभीरता से विचार करना होगा

मैं यहां बिंदु याद कर सकता हूं, लेकिन निम्नलिखित नहीं है जो नियंत्रक में ईवेंट हैंडलर के लिए मजबूत संदर्भ का गठन करता है?

  _canExecute = canExecute;