翻蚳è
ãã
æè¿ãç§ãåããŠãããããžã§ã¯ãã§ãã¡ã¢ãªãªãŒã¯ã®åé¡ã«ééããŸããã .NETã§ã®ã¡ã¢ãªç®¡çã«é¢ããèšäºããããªãœãŒã¹ã®æ£ãããªãªãŒã¹ã«é¢ããå®çšçãªæšå¥šäºé
ãŸã§ãå€ãã®èšäºãèªãã åŸãã€ãã³ããæ£ãã䜿çšããæ¹æ³ã説æããèšäºã«åºäŒããŸããã 圌女ã®ç¿»èš³ã玹ä»ããããšæããŸãã
ããã¯ãµã³ãããã¯ã¹ã®ãããã¯ã§ãHabrã§ããã«ã¢ã¯ã»ã¹ããŸããã
ã¯ããã«
CïŒã§éåžžã®ã€ãã³ãã䜿çšããå Žåãã€ãã³ãã«ãµãã¹ã¯ã©ã€ããããšãã€ãã³ããå«ããªããžã§ã¯ããããµãã¹ã¯ã©ã€ããããªããžã§ã¯ããžã®ãªã³ã¯ãäœæãããŸãã
ãœãŒã¹ãªããžã§ã¯ãããµãã¹ã¯ã©ã€ããªããžã§ã¯ããããé·ãåç¶ããå Žåãã¡ã¢ãªãªãŒã¯ãçºçããå¯èœæ§ããããŸãããµãã¹ã¯ã©ã€ããžã®ä»ã®åç
§ããªãå ŽåããœãŒã¹ãªããžã§ã¯ãã¯åŒãç¶ããããåç
§ããŸãã ãããã£ãŠããµãã¹ã¯ã©ã€ããããªããžã§ã¯ãã«ãã£ãŠå æãããŠããã¡ã¢ãªã¯ãã¬ããŒãžã³ã¬ã¯ã¿ãŒã«ãã£ãŠè§£æŸã§ããŸããã
ãã®åé¡ã解決ããå€ãã®ã¢ãããŒãããããŸãã ãã®èšäºã§ã¯ããããã®ããã€ãã調ã¹ãå©ç¹ãšæ¬ ç¹ã«ã€ããŠèª¬æããŸãã ãã¹ãŠã®ã¢ãããŒãã2ã€ã®éšåã«åããŸããã1ã€ã§ã¯ãã€ãã³ãã®ãœãŒã¹ãéåžžã®ã€ãã³ããæã€æ¢åã®ã¯ã©ã¹ã§ãããšæ³å®ããŸãã å¥ã®æ¹æ³ã§ã¯ãå
ã®ãªããžã§ã¯ãèªäœãå€æŽããŠãããŸããŸãªã¡ãœããã®åäœã確èªããŸãã
ã€ãã³ããšã¯äœã§ããïŒ
å€ãã®éçºè
ã¯ãã€ãã³ãã¯ããªã²ãŒãã®ãªã¹ãã§ãããšèããŠããŸãã ããã¯çå®ã§ã¯ãããŸããã ãåç¥ã®ããã«ãããªã²ãŒãã¯ãã«ããã£ã¹ãã«ããããšãã§ããŸã-äžåºŠã«ããã€ãã®æ©èœãžã®ãªã³ã¯ãå«ãŸããŸãïŒ
EventHandler eh = Method1; eh += Method2;
ã§ã¯ãã€ãã³ããšã¯äœã§ããïŒ ãããã¯ããããã£ã«äŒŒãŠããŸããå
éšã«ã¯ããªã²ãŒããã£ãŒã«ããå«ãŸããŠãããã¢ã¯ã»ã¹ã¯çŽæ¥æåŠãããŸãã ããªã²ãŒãã®ãããªãã¯ãã£ãŒã«ãïŒãŸãã¯ãããªãã¯ããããã£ïŒã«ãããã€ãã³ããã³ãã©ãŒã®ãªã¹ããå¥ã®ãªããžã§ã¯ãã«ãã£ãŠã¯ãªã¢ãããããã€ãã³ããå€éšããåŒã³åºãããããšããããŸããããœãŒã¹ãªããžã§ã¯ãããã®ã¿åŒã³åºãããå ŽåããããŸãã
ããããã£ã¯get / setã¡ãœããã®ãã¢ã§ãã ã€ãã³ãã¯ããã€ãã®è¿œå /åé€ã¡ãœããã§ãã
public event EventHandler MyEvent { add { ... } remove { ... } }
ãã³ãã©ãè¿œå ããã³åé€ããã¡ãœããã®ã¿ããããªãã¯ã§ããå¿
èŠããããŸãã ãã®å Žåãæ®ãã®ã¯ã©ã¹ã¯ãã³ãã©ãŒã®ãªã¹ããååŸã§ããããããã¯ãªã¢ããããšããã€ãã³ããçºçãããããšãã§ããŸããã
CïŒã§ã€ãã³ãã宣èšããããã®çãæ§æã¯èª€è§£ãæãå ŽåããããŸãã
public event EventHandler MyEvent;
å®éããã®ãããªã³ã³ãã€ã«ãšã³ããªã¯æ¬¡ã®ããã«å±éãããŸãã
private EventHandler _MyEvent; // public event EventHandler MyEvent { add { lock(this) { _MyEvent += value; } } remove { lock(this) { _MyEvent -= value; } } }
CïŒã§ã¯ãã€ãã³ãã¯ã宣èšãããŠãããªããžã§ã¯ãã䜿çšããŠãããã©ã«ãã§åæã䜿çšããŠå®è£
ãããŸãã ããã¯ãéã¢ã»ã³ãã©ã䜿çšããŠç¢ºèªã§ããŸããè¿œå ã¡ãœãããšåé€ã¡ãœããã¯ã[MethodImplïŒMethodImplOptions.SynchronizedïŒ]å±æ§ã§ããŒã¯ãããŸããããã¯ããªããžã§ã¯ãã®çŸåšã®ã€ã³ã¹ã¿ã³ã¹ã䜿çšããåæãšåçã§ãã
ã€ãã³ãã®ãµãã¹ã¯ã©ã€ããšãµãã¹ã¯ã©ã€ã解é€ã¯ãã¹ã¬ããã»ãŒããªæäœã§ãã ãã ããã¹ã¬ããã»ãŒãã€ãã³ãåŒã³åºãã¯éçºè
ã®è£éã«ä»»ãããŠãããéåžžã«é »ç¹ã«èª€ã£ãŠå®è¡ããŸãã
if (MyEvent != null) MyEvent(this, EventArgs.Empty);
å¥ã®äžè¬çãªãªãã·ã§ã³ã¯ãããŒã«ã«å€æ°ã«ããªã²ãŒããäºåã«ä¿åããããšã§ãã
EventHandler eh = MyEvent; if (eh != null) eh(this, EventArgs.Empty);
ãã®ã³ãŒãã¯ã¹ã¬ããã»ãŒãã§ããïŒ ã©ã®ããã«ã CïŒèšèªä»æ§ã§èª¬æãããŠããã¡ã¢ãªã¢ãã«ã«ãããšããã®äŸã¯ã¹ã¬ããã»ãŒãã§ã¯ãããŸãããJITã³ã³ãã€ã©ã¯ãã³ãŒããæé©åããããšã«ãããããŒã«ã«å€æ°ãåé€ã§ããŸãã ãã ãã.NETã©ã³ã¿ã€ã ïŒããŒãžã§ã³2.0以éïŒã¯ãã匷åãªã¡ã¢ãªã¢ãã«ãåããŠããããã®ã³ãŒãã§ã¯ã¹ã¬ããã»ãŒãã§ãã
ECMAä»æ§ã«ãããšãæ£ãã解決çã¯ãããã¯ïŒthisïŒãããã¯ã«ããŒã«ã«å€æ°ãå²ãåœãŠãããæ®çºæ§ãã£ãŒã«ãã䜿çšããŠããªã²ãŒããžã®åç
§ãä¿åããããšã§ãã
EventHandler eh; lock (this) { eh = MyEvent; } if (eh != null) eh(this, EventArgs.Empty);
ããŒã1ïŒãµãã¹ã¯ã©ã€ããŒåŽã®åŒ±ãã€ãã³ã
ãã®éšåã§ã¯ãéåžžã®ã€ãã³ãïŒãã³ãã©ãŒãžã®åç
§ãå«ãïŒãããããšãæ瀺ããããããã®ãµãã¹ã¯ãªãã·ã§ã³è§£é€ã¯ãµãã¹ã¯ã©ã€ããŒåŽã§è¡ãå¿
èŠããããŸãã
解決ç0ïŒç»é²è§£é€ããã ã
void RegisterEvent() { eventSource.Event += OnEvent; } void DeregisterEvent() { eventSource.Event -= OnEvent; } void OnEvent(object sender, EventArgs e) { ... }
ã·ã³ãã«ã§å¹æçã§ãå¯èœãªéã䜿çšããå¿
èŠããããŸãã ãã ãããªããžã§ã¯ãã䜿çšãããªããªã£ãåŸãDeregisterEventã¡ãœããã®åŒã³åºããåžžã«æäŸã§ãããšã¯éããŸããã Disposeã¡ãœããã®äœ¿çšãè©Šãããšãã§ããŸãããäžè¬çã«ã¢ã³ãããŒãžãªãœãŒã¹ã«äœ¿çšãããŸãã ãã®å Žåã®ãã¡ã€ãã©ã€ã¶ã¯æ©èœããŸãããå
ã®ãªããžã§ã¯ãããµãã¹ã¯ã©ã€ããåç
§ããŠãããããã¬ããŒãžã³ã¬ã¯ã¿ã¯ãããåŒã³åºããŸããã
ã¡ãªãããªããžã§ã¯ãã®äœ¿çšã«Disposeã®åŒã³åºããå«ãŸããå Žåã«äœ¿ããããã
çææ瀺çãªã¡ã¢ãªç®¡çã¯æ³šæãå¿
èŠã§ãã Disposeã¡ãœãããåŒã³åºãã®ãå¿ããããšããããŸãã
解決ç1ïŒåŒã³åºãããåŸã®ã€ãã³ãã®ãµãã¹ã¯ã©ã€ã解é€
void RegisterEvent() { eventSource.Event += OnEvent; } void OnEvent(object sender, EventArgs e) { if (!InUse) { eventSource.Event -= OnEvent; return; } ... }
ããã§ããµãã¹ã¯ã©ã€ãããŠãããªããžã§ã¯ãã䜿çšãããªããªã£ãããšã誰ããæããŠãããŠãæ°ã«ããå¿
èŠã¯ãããŸããã ã€ãã³ããåŒã³åºãããåŸãç§ãã¡èªèº«ãããã確èªããŸãã ãã ãããœãªã¥ãŒã·ã§ã³0ã䜿çšã§ããªãå ŽåãååãšããŠããªããžã§ã¯ãèªäœãã䜿çšãããŠãããã©ãããå€æããããšã¯ã§ããŸããã ãããŠãããªãããã®èšäºãèªãã§ãããšããäºå®ãèãããšããããããããã®ã±ãŒã¹ã®1ã€ã«åºããããã§ãããã
ãã®ãœãªã¥ãŒã·ã§ã³ã¯ãã§ã«ãœãªã¥ãŒã·ã§ã³0ã«è² ããŠããããšã«æ³šæããŠãã ãããã€ãã³ããããªã¬ãŒãããªãå Žåããµãã¹ã¯ã©ã€ããŒãå æããŠããã¡ã¢ãªãªãŒã¯ãçºçããŸãã éçSettingsChangedã€ãã³ãã«ãµãã¹ã¯ã©ã€ãããå€ãã®ãªããžã§ã¯ããæ³åããŠãã ããã ãããã®ãªããžã§ã¯ãã¯ãã¹ãŠãã€ãã³ããçºçãããŸã§ã¬ããŒãžã³ã¬ã¯ã¿ãŒã«ãã£ãŠã¯ãªãŒã³ã¢ãããããŸãã-ããã¯æ±ºããŠçºçããªãå¯èœæ§ããããŸãã
ã¡ãªãããã
çæã€ãã³ããããªã¬ãŒãããªãå Žåã®ã¡ã¢ãªãªãŒã¯ã ãªããžã§ã¯ãã䜿çšäžãã©ãããå€æããããšãå°é£ã§ãã
解決ç2ïŒåŒ±åç
§ã§ã©ãããã
ãã®ãœãªã¥ãŒã·ã§ã³ã¯ãã€ãã³ããã³ãã©ãŒã®ã³ãŒããã©ãããŒã¯ã©ã¹ã«é
眮ããããšãé€ããŠã以åã®ãœãªã¥ãŒã·ã§ã³ãšã»ãŒåãã§ããã©ãããŒã¯ã©ã¹ã¯ã
匱ããªã³ã¯ãä»ããŠã¢ã¯ã»ã¹ã§ãããµãã¹ã¯ã©ã€ããªããžã§ã¯ãã«åŒã³åºãããªãã€ã¬ã¯ãããŸãã 匱ããªã³ã¯ã䜿çšãããšããµãã¹ã¯ã©ã€ããªããžã§ã¯ãããŸã ååšãããã©ãããç°¡åã«ç¢ºèªã§ããŸãã
EventWrapper ew; void RegisterEvent() { ew = new EventWrapper(eventSource, this); } void OnEvent(object sender, EventArgs e) { ... } sealed class EventWrapper { SourceObject eventSource; WeakReference wr; public EventWrapper(SourceObject eventSource, ListenerObject obj) { this.eventSource = eventSource; this.wr = new WeakReference(obj); eventSource.Event += OnEvent; } void OnEvent(object sender, EventArgs e) { ListenerObject obj = (ListenerObject)wr.Target; if (obj != null) obj.OnEvent(sender, e); else Deregister(); } public void Deregister() { eventSource.Event -= OnEvent; } }
ã¡ãªããã¬ããŒãžã³ã¬ã¯ã¿ãŒããµãã¹ã¯ã©ã€ããŒã¡ã¢ãªã解æŸã§ããããã«ããŸãã
çæã€ãã³ãã倱æããªãå Žåãã©ãããŒãå æããã¡ã¢ãªãªãŒã¯ã åã€ãã³ãã®ã©ãããŒã¯ã©ã¹ãèšè¿°ããããšã¯ãç¹°ãè¿ãã³ãŒãã®æã§ãã
解決ç3ïŒãã¡ã€ãã©ã€ã¶ãŒã®ã€ãã³ããããµãã¹ã¯ã©ã€ã解é€ãã
åã®äŸã§ã¯ãEventWrapperãžã®ãªã³ã¯ãä¿åãããããªãã¯ã®Deregisterã¡ãœããããããŸããã ãã¡ã€ãã©ã€ã¶ïŒãã¹ãã©ã¯ã¿ïŒããµãã¹ã¯ã©ã€ãã«è¿œå ããããã䜿çšããŠã€ãã³ãã®ãµãã¹ã¯ãªãã·ã§ã³ã解é€ã§ããŸãã
~ListenerObject() { ew.Deregister(); }
ãã®ã¡ãœããã¯ã¡ã¢ãªãªãŒã¯ããç§ãã¡ãæããŸãããããªãã¯ããã«ãéãæããªããã°ãªããŸããïŒã¬ããŒãžã³ã¬ã¯ã¿ã¯ãã¡ã€ãã©ã€ã¶ã§ãªããžã§ã¯ããåé€ããã®ã«ããå€ãã®æéãè²»ãããŸãã ãµãã¹ã¯ã©ã€ããªããžã§ã¯ããåç
§ãããªããªããšïŒåŒ±ããªã³ã¯ãé€ãïŒãæåã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãçãæ®ããããé«ãäžä»£ã«è»¢éãããŸãã ãã®åŸãã¬ããŒãžã³ã¬ã¯ã¿ã¯ãã¡ã€ãã©ã€ã¶ãåŒã³åºããŸãããã®åŸã次ã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã§ãªããžã§ã¯ããåé€ã§ããŸãïŒæ°ããäžä»£ã§æ¢ã«ïŒã
ãã¡ã€ãã©ã€ã¶ã¯å¥ã®ã¹ã¬ããã§åŒã³åºãããããšã«ã泚æããŠãã ããã ããã«ãããã€ãã³ããµãã¹ã¯ãªãã·ã§ã³/ãµãã¹ã¯ãªãã·ã§ã³è§£é€ãã¹ã¬ããã»ãŒãã§ãªãæ¹æ³ã§å®è£
ãããŠããå Žåããšã©ãŒãçºçããå¯èœæ§ããããŸãã CïŒã®ã€ãã³ãã®ããã©ã«ãå®è£
ã¯ã¹ã¬ããã»ãŒãã§ã¯ãªãããšã«æ³šæããŠãã ããïŒ
ã¡ãªããã¬ããŒãžã³ã¬ã¯ã¿ãŒããµãã¹ã¯ã©ã€ããŒã¡ã¢ãªã解æŸã§ããããã«ããŸãã ã©ãããŒãå æããã¡ã¢ãªãªãŒã¯ã¯ãããŸããã
çæãã¡ã€ãã©ã€ã¶ã䜿çšãããšãæªäœ¿çšã®ãªããžã§ã¯ããåé€ãããåã«ã¡ã¢ãªã«æ®ãæéãé·ããªããŸãã ã€ãã³ãã®ã¹ã¬ããã»ãŒããªå®è£
ãå¿
èŠã§ãã éè€ã³ãŒããããããã
解決ç4ïŒã©ãããŒãåå©çšãã
以äžã®ã³ãŒãã«ã¯ãåå©çšå¯èœãªã©ãããŒã¯ã©ã¹ãå«ãŸããŠããŸãã ã©ã ãåŒã䜿çšããŠãå¥ã®ã³ãŒããæž¡ããŸããã€ãã³ãããµãã¹ã¯ã©ã€ãããã€ãã³ããããµãã¹ã¯ã©ã€ãã解é€ããã€ãã³ãããã©ã€ããŒãã¡ãœããã«è»¢éããŸãã
eventWrapper = WeakEventHandler.Register( eventSource, (s, eh) => s.Event += eh, // (s, eh) => s.Event -= eh, // this, // (me, sender, args) => me.OnEvent(sender, args) // );
è¿ãããeventWrapperã€ã³ã¹ã¿ã³ã¹ã«ã¯ããããªãã¯ã¡ãœããã1ã€ã ããããŸã-ç»é²è§£é€ã ã©ã ãåŒãèšè¿°ãããšãã¯æ³šæãå¿
èŠã§ããã©ã ãåŒã¯ããªã²ãŒãã«ã³ã³ãã€ã«ãããããããªããžã§ã¯ããžã®åç
§ãå«ããããšãã§ããŸãã ããããå å
¥è
ãç§ãšããŠæ»ã£ãŠããçç±ã§ãã ïŒmeãsenderãargsïŒ=> this.OnEventïŒsenderãargsïŒãšæžããå Žåãã©ã ãåŒãthiså€æ°ã«ã¢ã¿ãããããã¯ããŒãžã£ãŒãäœæãããŸãã ãŸããWeakEventHandlerã«ã¯ã€ãã³ããçºçãããããªã²ãŒããžã®ãªã³ã¯ãå«ãŸããŠãããããã©ãããŒãããµãã¹ã¯ã©ã€ããŒãžã®ã匷åãªãïŒéåžžã®ïŒãªã³ã¯ã«ãªããŸãã 幞ããªããšã«ãããªã²ãŒããå€æ°ããã£ããã£ãããã©ããã確èªããæ©äŒããããŸãããã®ãããªã©ã ãåŒã®å Žåãã³ã³ãã€ã©ã¯ã€ã³ã¹ã¿ã³ã¹ã¡ãœãããäœæããŸãã ãã以å€ã®å Žåãã¡ãœããã¯éçã«ãªããŸãã WeakEventHandlerã¯ãDelegate.Method.IsStaticãã©ã°ã䜿çšããŠããããã§ãã¯ããã©ã ãåŒã®ã¹ãã«ãæ£ãããªãå Žåã¯äŸå€ãã¹ããŒããŸãã
ãã®ã¢ãããŒãã«ãããã©ãããŒãåå©çšã§ããŸãããããªã²ãŒãã®ã¿ã€ãããšã«ç¬èªã®ã©ãããŒã¯ã©ã¹ãå¿
èŠã§ãã System.EventHandlerãšSystem.EventHandlerãç©æ¥µçã«äœ¿çšã§ãããããããŸããŸãªçš®é¡ã®ããªã²ãŒããããå Žåã¯ãããããã¹ãŠãèªååããå¿
èŠããããŸãã ããã«ã¯ãã³ãŒãçæãŸãã¯System.Reflection.Emitã¹ããŒã¹ã¿ã€ãã䜿çšã§ããŸãã
ã¡ãªããã¬ããŒãžã³ã¬ã¯ã¿ãŒããµãã¹ã¯ã©ã€ããŒã¡ã¢ãªã解æŸã§ããããã«ããŸãã è¿œå ã³ãŒãã®ãµã€ãºã¯ããã»ã©å€§ãããããŸããã
çæã€ãã³ãã倱æããªãå Žåãã©ãããŒãå æããã¡ã¢ãªãªãŒã¯ã
解決ç5ïŒWeakEventManager
WPFã«ã¯ãWeakEventManagerã¯ã©ã¹ãä»ãããµãã¹ã¯ã©ã€ãåŽã®åŒ±ãã€ãã³ãã®çµã¿èŸŒã¿ãµããŒãããããŸãã ã©ãããŒã䜿çšãã以åã®ãœãªã¥ãŒã·ã§ã³ãšåæ§ã«æ©èœããŸãããWeakEventManagerã®åäžã€ã³ã¹ã¿ã³ã¹ãè€æ°ã®ã€ãã³ããœãŒã¹ãšè€æ°ã®ãµãã¹ã¯ã©ã€ããŒéã®ã©ãããŒãšããŠæ©èœããç¹ãç°ãªããŸãã ãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ã1ã€ãããªããããWeakEventManagerã¯ãã€ãã³ããããªã¬ãŒãããªãå Žåã§ãã¡ã¢ãªãªãŒã¯ãåé¿ããŸããå¥ã®ã€ãã³ãã«ãµãã¹ã¯ã©ã€ããããšãå€ããµãã¹ã¯ãªãã·ã§ã³ã®ãªã¹ããã¯ãªã¢ãããå ŽåããããŸãã ãããã®ã¯ãªãŒã³ã¢ããã¯ãWPFã¡ãã»ãŒãžã«ãŒããå®è¡ãããŠããã¹ã¬ããã§WPFãããŒãžã£ãŒã«ãã£ãŠå®è¡ãããŸãã
WeakEventManagerã«ã¯è¿œå ã®å¶éããããŸããsenderãã©ã¡ãŒã¿ãŒã®æ£ããèšå®ãå¿
èŠã§ãã button.Clickã€ãã³ãã«äœ¿çšãããšãsender == buttonã®ã€ãã³ãã®ã¿ããµãã¹ã¯ã©ã€ããŒã«æž¡ãããŸãã äžéšã®ã€ãã³ãå®è£
ã§ã¯ããã³ãã©ãŒãä»ã®ã€ãã³ãã«æ·»ä»ã§ããŸãã
public event EventHandler Event { add { anotherObject.Event += value; } remove { anotherObject.Event -= value; } }
ãã®ãããªã€ãã³ãã¯ãWeakEventManagerã§ã¯äœ¿çšã§ããŸããã
ã€ãã³ãããšã«1ã€ã®WeakEventManagerãã¹ã¬ããããšã«1ã€ã®ã€ã³ã¹ã¿ã³ã¹ã ãã®ãããªã€ãã³ããã³ãŒããã©ã³ã¯ã§æ±ºå®ããããã®æšå¥šãã³ãã¬ãŒãã¯ãMSDNã®èšäº
ãWeakEvent Templatesãã«ãããŸãã
幞ããªããšã«ããžã§ããªãã¯ã䜿çšããŠãããç°¡çŽ åã§ããŸãã
public sealed class ButtonClickEventManager : WeakEventManagerBase<ButtonClickEventManager, Button> { protected override void StartListening(Button source) { source.Click += DeliverEvent; } protected override void StopListening(Button source) { source.Click -= DeliverEvent; } }
DeliverEventã¯åŒæ°ãšããŠïŒãªããžã§ã¯ããEventArgsïŒãåãå
¥ããClickã€ãã³ãã¯åŒæ°ïŒãªããžã§ã¯ããRoutedEventArgsïŒãæäŸããããšã«æ³šæããŠãã ããã CïŒã§ã¯ãããªã²ãŒãã®ã¿ã€ãéã®å€æã¯ãµããŒããããŠããŸããã
ãã¡ãœããã®ã°ã«ãŒãããããªã²ãŒããäœæããéã®é¿åŠã¯ãµããŒããããŠã
ãŸã ã
ã¡ãªããã¬ããŒãžã³ã¬ã¯ã¿ãŒããµãã¹ã¯ã©ã€ããŒã¡ã¢ãªã解æŸã§ããããã«ããŸãã ã©ãããŒãå æããŠããã¡ã¢ãªã解æŸã§ããŸãã
çæãã®æ¹æ³ã¯ãå®è£
ãWPFã«é¢é£ä»ããããŠãããããã°ã©ãã£ã«ã«ã€ã³ã¿ãŒãã§ã€ã¹ããªãã¢ããªã±ãŒã·ã§ã³ã«ã¯ããŸãé©ããŠããŸããã
ããŒã2ïŒãœãŒã¹åŽã®åŒ±ãã€ãã³ã
ãã®ããŒãã§ã¯ãã€ãã³ããå«ãå
ã®ãªããžã§ã¯ããå€æŽããŠã匱ãã€ãã³ããå®è£
ããæ¹æ³ãèŠãŠãããŸãã 以äžã«ææ¡ãããã¹ãŠã®ãœãªã¥ãŒã·ã§ã³ã¯ããµãã¹ã¯ã©ã€ããŒåŽã®åŒ±ãã€ãã³ãã®å®è£
ãããå©ç¹ããããŸããã¹ã¬ããã»ãŒããªãµãã¹ã¯ãªãã·ã§ã³/ãµãã¹ã¯ãªãã·ã§ã³è§£é€ãç°¡åã«è¡ãããšãã§ããŸãã
解決ç0ïŒã€ã³ã¿ãŒãã§ãŒã¹
WeakEventManagerã¯ããã®ããŒãã§èšåãã䟡å€ããããŸãã ã©ãããŒãšããŠãéåžžã®ã€ãã³ãïŒãµãã¹ã¯ã©ã€ããŒåŽïŒãçµåããŸãããã¯ã©ã€ã¢ã³ãïŒãœãŒã¹ãªããžã§ã¯ãåŽïŒã«åŒ±ãã€ãã³ããæäŸããããšãã§ããŸãã
IWeakEventListenerã€ã³ã¿ãŒãã§ã€ã¹ããããŸãã ãã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ãããµãã¹ã¯ã©ã€ãã®å ŽåããœãŒã¹ãªããžã§ã¯ãã¯ãŠã£ãŒã¯ãªã³ã¯ã䜿çšããŠåç
§ãããå®è£
ãããReceiveWeakEventã¡ãœãããåŒã³åºãããŸãã
ã¡ãªããã·ã³ãã«ã§å¹æçã
çæãªããžã§ã¯ããå€ãã®ã€ãã³ãã«ãµãã¹ã¯ã©ã€ããããå ŽåãReceiveWeakEventã®å®è£
ã§ã¯ãã€ãã³ãã®ã¿ã€ããšãœãŒã¹ã«é¢ããäžé£ã®ãã§ãã¯ãèšè¿°ããå¿
èŠããããŸãã
解決ç1ïŒåŒ±ãå§ä»»åç
§
ããã¯WPFã§äœ¿çšãããå¥ã®ã¢ãããŒãã§ããCommandManager.InvalidateRequeryã¯éåžžã®ã€ãã³ãã®ããã«èŠããŸãããããã§ã¯ãããŸããã ããªã²ãŒããžã®åŒ±ãåç
§ãå«ãŸããŠãããããéçã€ãã³ãã«ãµãã¹ã¯ã©ã€ãããŠãã¡ã¢ãªãªãŒã¯ã¯çºçããŸããã
ããã¯ç°¡åãªãœãªã¥ãŒã·ã§ã³ã§ãããã€ãã³ããµãã¹ã¯ã©ã€ããŒã¯ç°¡åã«ãããå¿ãããã誀解ãããããå¯èœæ§ããããŸãã
CommandManager.InvalidateRequery += OnInvalidateRequery;
åé¡ã¯ãCommandManagerã«ã¯åŒ±ãããªã²ãŒããªã³ã¯ã®ã¿ãå«ãŸãããµãã¹ã¯ã©ã€ãã«ã¯ããªã²ãŒããªã³ã¯ããŸã£ããå«ãŸããŠããªãããšã§ãã ãããã£ãŠã次ã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã§ããªã²ãŒããåé€ããããµãã¹ã¯ã©ã€ãããŠãããªããžã§ã¯ãããŸã 䜿çšäžã§ãã£ãŠããOnInvalidateRequeryã¯æ©èœããªããªããŸãã ããªã²ãŒããã¡ã¢ãªå
ã«ããããã«ã¯ããµãã¹ã¯ã©ã€ããŒãå¿çããå¿
èŠããããŸãã
class Listener { EventHandler strongReferenceToDelegate; public void RegisterForEvent() { strongReferenceToDelegate = new EventHandler(OnInvalidateRequery); CommandManager.InvalidateRequery += strongReferenceToDelegate; } void OnInvalidateRequery(...) {...} }
ã¡ãªããããªã²ãŒãã«ãã£ãŠå æãããŠããã¡ã¢ãªã¯è§£æŸãããŸãã
çæããªã²ãŒããžã®ã匷åãªããªã³ã¯ã®ä»å ãå¿ãããšãæåã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãŸã§ã€ãã³ããçºçããŸãã ããã«ããããšã©ãŒãèŠã€ããã®ãé£ãããªããŸãã
解決ç2ïŒãªããžã§ã¯ã+ãã©ã¯ãŒããŒ
WeakEventManagerã¯ãœãªã¥ãŒã·ã§ã³0ã«é©åããŸããããWeakEventHandlerã©ãããŒã¯ãã®ãœãªã¥ãŒã·ã§ã³ã«é©åããŸãã<objectãForwarderDelegate>ãã¢ãç»é²ããŸãã
eventSource.AddHandler(this, (me, sender, args) => ((ListenerObject)me).OnEvent(sender, args));
ã¡ãªããã·ã³ãã«ã§å¹æçã
çæã€ãã³ããèšé²ããçããæ¹æ³ã ãªãã€ã¬ã¯ãã©ã ãåŒã«ã¯åå€æãå¿
èŠã§ãã
解決ç3ïŒSmartWeakEvent
以äžã«ç€ºãSmartWeakEventã¯ãéåžžã®.NETã€ãã³ãã®ããã«èŠãããã匱ããµãã¹ã¯ã©ã€ããŒãªã³ã¯ãæ ŒçŽããã€ãã³ããæäŸããŸãã T.O. ããªã²ãŒããžã®ã匷åãªããªã³ã¯ãç¶æããå¿
èŠã¯ãããŸããã
void RegisterEvent() { eventSource.Event += OnEvent; } void OnEvent(object sender, EventArgs e) { ... }
ã€ãã³ããå®çŸ©ããŸãã
SmartWeakEvent<EventHandler> _event = new SmartWeakEvent<EventHandler>(); public event EventHandler Event { add { _event.Add(value); } remove { _event.Remove(value); } } public void RaiseEvent() { _event.Raise(this, EventArgs.Empty); }
ã©ã®ããã«æ©èœããŸããïŒ Delegate.Targetããã³Delegate.Methodã®ããããã£ã䜿çšããŠãåããªã²ãŒãã¯ã¿ãŒã²ãããªããžã§ã¯ãïŒåŒ±åç
§ã䜿çšããŠæ ŒçŽïŒãšMethodInfoã«åå²ãããŸãã ã€ãã³ããçºçãããšããªãã¬ã¯ã·ã§ã³ã䜿çšããŠã¡ãœãããåŒã³åºãããŸãã
ãã®ã¡ãœããã®è匱æ§ã¯ã誰ããå¿åã¡ãœãããã€ãã³ããã³ãã©ãšããŠã¢ã¿ããã§ããããšã§ãã
int localVariable = 42; eventSource.Event += delegate { Console.WriteLine(localVariable); };
ãã®å Žåãã¿ãŒã²ããã¯ãã³ã¬ã¯ã¿ãŒã«ãã£ãŠããã«åé€ã§ããã¯ããŒãžã£ãŒã§ãã ãããžã®ãªã³ã¯ã¯ãããŸããã ãã ããSmartWeakEventã¯ãã®ãããªå Žåãæ€åºããŠäŸå€ãã¹ããŒã§ãããããã€ãã³ããã³ãã©ãŒã¯äºæ³ãããæ©ãã¢ã³ã¿ã€ããããããããããã°ã«åé¡ã¯ãªãã¯ãã§ãã
if (d.Method.DeclaringType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Length != 0) throw new ArgumentException(...)
ã¡ãªããããã¯æ¬åœã«åŒ±ãåºæ¥äºã®ããã«èŠããŸãã åé·ã³ãŒãã¯ã»ãšãã©ãããŸããã
çæãªãã¬ã¯ã·ã§ã³ã«ããã¡ãœããã®å®è¡ã¯ããªãé
ãã§ãã ãã©ã€ããŒãã¡ãœãããå®è£
ãããããéšåçãªæš©éã§ã¯æ©èœããŸããã
解決ç4ïŒFastSmartWeakEvent
æ©èœãšäœ¿çšæ¹æ³ã¯SmartWeakEventã䜿çšãããœãªã¥ãŒã·ã§ã³ãšäŒŒãŠããŸãããããã©ãŒãã³ã¹ã¯ã¯ããã«é«ããªã£ãŠããŸãã
次ã«ã2ã€ã®ããªã²ãŒããæã€ã€ãã³ãã®ãã¹ãçµæã瀺ããŸãïŒ1ã€ã¯ã€ã³ã¹ã¿ã³ã¹ã¡ãœãããåç
§ãããã1ã€ã¯éçã¡ãœãããåç
§ããŸãïŒã
éåžžïŒã匷ããïŒã€ãã³ã... 16 948 785 1ç§ãããã®åŒã³åºã
ã¹ããŒããŠã£ãŒã¯ã€ãã³ã... 91,960ã³ãŒã«/ç§
é«éã¹ããŒããŠã£ãŒã¯ã€ãã³ã... 4,901,840ã³ãŒã«/ç§
ã©ã®ããã«æ©èœããŸããïŒ ã¡ãœããã®å®è¡ã«ãªãã¬ã¯ã·ã§ã³ã䜿çšããªããªããŸããã 代ããã«ãSystem.Reflection.Emit.DynamicMethodã䜿çšããŠããã°ã©ã ã®å®è¡äžã«ã¡ãœããïŒä»¥åã®ãœãªã¥ãŒã·ã§ã³ã®ã¡ãœãããšåæ§ïŒãã³ã³ãã€ã«ããŸãã
ã¡ãªããæ¬åœã«åŒ±ãã€ãã³ãã®ããã«èŠããŸãã åé·ã³ãŒãã¯ã»ãšãã©ãããŸããã
çæãã©ã€ããŒãã¡ãœãããå®è£
ãããããéšåçãªæš©éã§ã¯æ©èœããŸããã
ç³ãåº
- WeakEventManagerã¯ãWPFã¢ããªã±ãŒã·ã§ã³ã®GUIã¹ã¬ããã§æ©èœãããã¹ãŠã®ãã®ã«äœ¿çšããŸãïŒããšãã°ãã¢ãã«ãªããžã§ã¯ãã€ãã³ãã«ãµãã¹ã¯ã©ã€ããããŠãŒã¶ãŒã³ã³ãããŒã«çšïŒ
- 匱ãã€ãã³ããæäŸããå Žåã¯ãFastSmartWeakEventã䜿çšããŸã
- ã€ãã³ãããµãã¹ã¯ã©ã€ãããå Žåã¯ãWeakEventHandlerã䜿çšããŸãã