예제 #1
0
        /// <summary> Helps to safely raise an event.
        /// </summary>
        /// <param name="delegate">The event delegate (<see cref="EventHandler"/>, <see cref="EventHandler{T}"/></param>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        /// <param name="uniqueId">A unique ID</param>
        /// <exception cref="MultiTargetInvocationException"></exception>
        public static void Raise(Delegate @delegate, object sender, EventArgs e, string uniqueId)
        {
            if (@delegate == null)
            {
                return;
            }

            #region simple invoke (conditional)
#if (false) // simple invoke the delegate w/o any other stuff (DynamicInvoke is slow!)
            try{
                @delegate.DynamicInvoke(new[] { sender, e });
            } catch (Exception ex) {
                if (ObjectVM.IsInDesignMode)
                {
                    return;            // ignore designtime error
                }
                throw;                 // possible breakpoint for debug
            }
            return;
#endif
            #endregion

//			var exceptions=new List<Exception>();
            var exceptions     = (List <Exception>)null;     //don't collect, do throw directly
            var invocationList = @delegate.GetInvocationList();

            #region Trace (conditional)
#if (false)
            Debug.WriteLine("=>Raise event: " + "(" + invocationList.Length + " target" + (invocationList.Length != 1?"s":"") + ")");
            foreach (var d in invocationList)
            {
                var targetType = d.Target.GetType().FullName;
                var method     = d.Method.ToString();
                Debug.WriteLine("=>\t" + "Target: " + targetType + " " + method);
            }
            Debug.WriteLine("=>\t" + "Raising method: " + sender.GetType().FullName + "." + new StackFrame(1).GetMethod());

            // MemberPath (ObjectVM/ObjectBM)
            var memberPathProperty = sender.GetType().GetProperty("MemberPath");
            if (memberPathProperty != null)
            {
                var memberPath = memberPathProperty.GetValue(sender, null);
                Debug.WriteLine("=>\t" + "MemberPath: " + memberPath);
            }
#endif
            #endregion

            var isInvokeRequired = ApplicationDispatcher.IsInvokeRequired;
            foreach (var d in invocationList)
            {
                #region DEBUG (conditional)
#if (false)
                Debug.WriteLine(string.Format("=>Raise event: #{0} {1} {2}",
                                              ++InvocationCount,
                                              DebugUtil.FormatTypeName(@delegate),
                                              "Target: " + DebugUtil.FormatTypeName(d.Target) + "." + d.Method.Name
                                              ));
#endif
                #endregion
                // EXPERIMENTAL ==>
                // workaround for TargetInvocationException --> InvalidOperationException:
                //   "The calling thread cannot access this object because a different thread owns it."
                // e.g. System.Windows.Input.CanExecuteChangedEventManager+HandlerSink, PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
                if (isInvokeRequired)
                {
                    if (d.Target.GetType().FullName == "System.Windows.Input.CanExecuteChangedEventManager+HandlerSink")
                    {
                        InvokeAppDispatcher(d, sender, e, exceptions);
                    }
                    else if (d.Target.GetType().FullName == "System.Windows.Data.ListCollectionView")
                    {
                        InvokeAppDispatcher(d, sender, e, exceptions);
                    }
                    /*??*/ else if (d.Target.GetType().Assembly.GetName().Name == "PresentationCore")
                    {
                        InvokeAppDispatcher(d, sender, e, exceptions);
                    }
                    else
                    {
                        Invoke(d, sender, e, exceptions);
                    }
                }
                //<==
                else
                {
                    Invoke(d, sender, e, exceptions);
                }
            }

            if (exceptions != null && exceptions.Count > 0)
            {
                var ex = new MultiTargetInvocationException(exceptions);
                #region DESIGNER
                if (IsInDesignMode)
                {
//					Trace.Write("=>Begin:" + exceptionCount + "######################################################################################################################################"+"\n");
                    Trace.Write("=>An unhandled exception has occured. Trying to continue." + "\n" + ex.ToString() + "\n");
                    foreach (var exception in exceptions)
                    {
                        Trace.Write("--------------------------------------------------------------------------------------------------------------------------------------" + "\n"
                                    + exception.ToString() + "\n");
                    }
//					Trace.Write("=>End :" + exceptionCount + "######################################################################################################################################"+"\n");
                    return;
                }
                #endregion
                throw ex;
            }
        }