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