PageRenderTime 38ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/V2.2/trunk/CAL/Desktop/Composite.Presentation/Commands/WeakEventHandlerManager.cs

#
C# | 177 lines | 115 code | 17 blank | 45 comment | 24 complexity | 8ac701770fcd7564f724354dad48d690 MD5 | raw file
  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.Linq;
  20. using System.Text;
  21. using System.Windows.Threading;
  22. using System.Windows;
  23. namespace Microsoft.Practices.Composite.Presentation.Commands
  24. {
  25. /// <summary>
  26. /// Handles management and dispatching of EventHandlers in a weak way.
  27. /// </summary>
  28. internal static class WeakEventHandlerManager
  29. {
  30. ///<summary>
  31. /// Invokes the handlers
  32. ///</summary>
  33. ///<param name="sender"></param>
  34. ///<param name="handlers"></param>
  35. public static void CallWeakReferenceHandlers(object sender, List<WeakReference> handlers)
  36. {
  37. if (handlers != null)
  38. {
  39. // Take a snapshot of the handlers before we call out to them since the handlers
  40. // could cause the array to me modified while we are reading it.
  41. EventHandler[] callees = new EventHandler[handlers.Count];
  42. int count = 0;
  43. //Clean up handlers
  44. count = CleanupOldHandlers(handlers, callees, count);
  45. // Call the handlers that we snapshotted
  46. for (int i = 0; i < count; i++)
  47. {
  48. CallHandler(sender, callees[i]);
  49. }
  50. }
  51. }
  52. private static void CallHandler(object sender, EventHandler eventHandler)
  53. {
  54. DispatcherProxy dispatcher = DispatcherProxy.CreateDispatcher();
  55. if (eventHandler != null)
  56. {
  57. if (dispatcher != null && !dispatcher.CheckAccess())
  58. {
  59. dispatcher.BeginInvoke((Action<object, EventHandler>)CallHandler, sender, eventHandler);
  60. }
  61. else
  62. {
  63. eventHandler(sender, EventArgs.Empty);
  64. }
  65. }
  66. }
  67. /// <summary>
  68. /// Hides the dispatcher mis-match between Silverlight and .Net, largely so code reads a bit easier
  69. /// </summary>
  70. private class DispatcherProxy
  71. {
  72. Dispatcher innerDispatcher;
  73. private DispatcherProxy(Dispatcher dispatcher)
  74. {
  75. innerDispatcher = dispatcher;
  76. }
  77. public static DispatcherProxy CreateDispatcher()
  78. {
  79. DispatcherProxy proxy = null;
  80. #if SILVERLIGHT
  81. if (Deployment.Current == null)
  82. return null;
  83. proxy = new DispatcherProxy(Deployment.Current.Dispatcher);
  84. #else
  85. if (Application.Current == null)
  86. return null;
  87. proxy = new DispatcherProxy(Application.Current.Dispatcher);
  88. #endif
  89. return proxy;
  90. }
  91. public bool CheckAccess()
  92. {
  93. return innerDispatcher.CheckAccess();
  94. }
  95. public DispatcherOperation BeginInvoke(Delegate method, params Object[] args)
  96. {
  97. #if SILVERLIGHT
  98. return innerDispatcher.BeginInvoke(method, args);
  99. #else
  100. return innerDispatcher.BeginInvoke(method, DispatcherPriority.Normal, args);
  101. #endif
  102. }
  103. }
  104. private static int CleanupOldHandlers(List<WeakReference> handlers, EventHandler[] callees, int count)
  105. {
  106. for (int i = handlers.Count - 1; i >= 0; i--)
  107. {
  108. WeakReference reference = handlers[i];
  109. EventHandler handler = reference.Target as EventHandler;
  110. if (handler == null)
  111. {
  112. // Clean up old handlers that have been collected
  113. handlers.RemoveAt(i);
  114. }
  115. else
  116. {
  117. callees[count] = handler;
  118. count++;
  119. }
  120. }
  121. return count;
  122. }
  123. ///<summary>
  124. /// Adds a handler to the supplied list in a weak way.
  125. ///</summary>
  126. ///<param name="handlers">Existing handler list. It will be created if null.</param>
  127. ///<param name="handler">Handler to add.</param>
  128. ///<param name="defaultListSize">Default list size.</param>
  129. public static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
  130. {
  131. if (handlers == null)
  132. {
  133. handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
  134. }
  135. handlers.Add(new WeakReference(handler));
  136. }
  137. ///<summary>
  138. /// Removes an event handler from the reference list.
  139. ///</summary>
  140. ///<param name="handlers">Handler list to remove reference from.</param>
  141. ///<param name="handler">Handler to remove.</param>
  142. public static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
  143. {
  144. if (handlers != null)
  145. {
  146. for (int i = handlers.Count - 1; i >= 0; i--)
  147. {
  148. WeakReference reference = handlers[i];
  149. EventHandler existingHandler = reference.Target as EventHandler;
  150. if ((existingHandler == null) || (existingHandler == handler))
  151. {
  152. // Clean up old handlers that have been collected
  153. // in addition to the handler that is to be removed.
  154. handlers.RemoveAt(i);
  155. }
  156. }
  157. }
  158. }
  159. }
  160. }