Prism中的WeakEventHandlerManager

View Code
  1 //===================================================================================
  2 // Microsoft patterns & practices
  3 // Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4 //===================================================================================
  5 // Copyright (c) Microsoft Corporation.  All rights reserved.
  6 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8 // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9 // FITNESS FOR A PARTICULAR PURPOSE.
 10 //===================================================================================
 11 // The example companies, organizations, products, domain names,
 12 // e-mail addresses, logos, people, places, and events depicted
 13 // herein are fictitious.  No association with any real company,
 14 // organization, product, domain name, email address, logo, person,
 15 // places, or events is intended or should be inferred.
 16 //===================================================================================
 17 using System;
 18 using System.Collections.Generic;
 19 using System.Windows.Threading;
 20 using System.Windows;
 21 
 22 namespace Microsoft.Practices.Prism.Commands
 23 {
 24     /// <summary>
 25     /// Handles management and dispatching of EventHandlers in a weak way.
 26     /// </summary>
 27     internal static class WeakEventHandlerManager
 28     {
 29         ///<summary>
 30         /// Invokes the handlers 
 31         ///</summary>
 32         ///<param name="sender"></param>
 33         ///<param name="handlers"></param>
 34         public static void CallWeakReferenceHandlers(object sender, List<WeakReference> handlers)
 35         {
 36             if (handlers != null)
 37             {
 38                 // Take a snapshot of the handlers before we call out to them since the handlers
 39                 // could cause the array to me modified while we are reading it.
 40                 EventHandler[] callees = new EventHandler[handlers.Count];
 41                 int count = 0;
 42 
 43                 //Clean up handlers
 44                 count = CleanupOldHandlers(handlers, callees, count);
 45 
 46                 // Call the handlers that we snapshotted
 47                 for (int i = 0; i < count; i++)
 48                 {
 49                     CallHandler(sender, callees[i]);
 50                 }
 51             }
 52         }
 53 
 54         private static void CallHandler(object sender, EventHandler eventHandler)
 55         {
 56             DispatcherProxy dispatcher = DispatcherProxy.CreateDispatcher();
 57 
 58             if (eventHandler != null)
 59             {
 60                 if (dispatcher != null && !dispatcher.CheckAccess())
 61                 {
 62                     dispatcher.BeginInvoke((Action<object, EventHandler>)CallHandler, sender, eventHandler);
 63                 }
 64                 else
 65                 {
 66                     eventHandler(sender, EventArgs.Empty);
 67                 }
 68             }
 69         }
 70 
 71         /// <summary>
 72         /// Hides the dispatcher mis-match between Silverlight and .Net, largely so code reads a bit easier
 73         /// </summary>
 74         private class DispatcherProxy
 75         {
 76             Dispatcher innerDispatcher;
 77 
 78             private DispatcherProxy(Dispatcher dispatcher)
 79             {
 80                 innerDispatcher = dispatcher;
 81             }
 82 
 83             public static DispatcherProxy CreateDispatcher()
 84             {
 85                 DispatcherProxy proxy = null;
 86 #if SILVERLIGHT
 87                 if (Deployment.Current == null)
 88                     return null;
 89 
 90                 proxy = new DispatcherProxy(Deployment.Current.Dispatcher);
 91 #else
 92                 if (Application.Current == null)
 93                     return null;
 94 
 95                 proxy = new DispatcherProxy(Application.Current.Dispatcher);
 96 #endif
 97                 return proxy;
 98 
 99             }
100 
101             public bool CheckAccess()
102             {
103                 return innerDispatcher.CheckAccess();
104             }
105 
106             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Windows.Threading.Dispatcher.#BeginInvoke(System.Delegate,System.Windows.Threading.DispatcherPriority,System.Object[])")]
107             public DispatcherOperation BeginInvoke(Delegate method, params Object[] args)
108             {
109 #if SILVERLIGHT
110                 return innerDispatcher.BeginInvoke(method, args);
111 #else
112                 return innerDispatcher.BeginInvoke(method, DispatcherPriority.Normal, args);
113 #endif
114             }
115         }
116 
117         private static int CleanupOldHandlers(List<WeakReference> handlers, EventHandler[] callees, int count)
118         {
119             for (int i = handlers.Count - 1; i >= 0; i--)
120             {
121                 WeakReference reference = handlers[i];
122                 EventHandler handler = reference.Target as EventHandler;
123                 if (handler == null)
124                 {
125                     // Clean up old handlers that have been collected
126                     handlers.RemoveAt(i);
127                 }
128                 else
129                 {
130                     callees[count] = handler;
131                     count++;
132                 }
133             }
134             return count;
135         }
136 
137         ///<summary>
138         /// Adds a handler to the supplied list in a weak way.
139         ///</summary>
140         ///<param name="handlers">Existing handler list.  It will be created if null.</param>
141         ///<param name="handler">Handler to add.</param>
142         ///<param name="defaultListSize">Default list size.</param>
143         public static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
144         {
145             if (handlers == null)
146             {
147                 handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
148             }
149 
150             handlers.Add(new WeakReference(handler));
151         }
152 
153         ///<summary>
154         /// Removes an event handler from the reference list.
155         ///</summary>
156         ///<param name="handlers">Handler list to remove reference from.</param>
157         ///<param name="handler">Handler to remove.</param>
158         public static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
159         {
160             if (handlers != null)
161             {
162                 for (int i = handlers.Count - 1; i >= 0; i--)
163                 {
164                     WeakReference reference = handlers[i];
165                     EventHandler existingHandler = reference.Target as EventHandler;
166                     if ((existingHandler == null) || (existingHandler == handler))
167                     {
168                         // Clean up old handlers that have been collected
169                         // in addition to the handler that is to be removed.
170                         handlers.RemoveAt(i);
171                     }
172                 }
173             }
174         }
175     }
176 }

 

posted @ 2012-12-12 07:55  easy5  阅读(354)  评论(0编辑  收藏  举报