public void TryCompare(int p1, int p2, IxCoreColleague c1, IxCoreColleague c2)
		{
			var sut = new TupleComparer();
			var tuple1 = Tuple.Create (p1, c1);
			var tuple2 = Tuple.Create (p2, c2);
			Assert.That(sut.Compare(tuple1, tuple2), Is.LessThan(0));
			Assert.That(sut.Compare(tuple2, tuple1), Is.GreaterThan(0));
		}
Beispiel #2
0
        public void TryCompare(int p1, int p2, IxCoreColleague c1, IxCoreColleague c2)
        {
            var sut    = new TupleComparer();
            var tuple1 = Tuple.Create(p1, c1);
            var tuple2 = Tuple.Create(p2, c2);

            Assert.That(sut.Compare(tuple1, tuple2), Is.LessThan(0));
            Assert.That(sut.Compare(tuple2, tuple1), Is.GreaterThan(0));
        }
Beispiel #3
0
        /// <summary>
        /// Constructor with paramters being required.
        /// </summary>
        /// <param name="mediator">Mediator that will handle the collegue during its temporary liketime.</param>
        /// <param name="temporaryColleague"></param>
        public TemporaryColleagueParameter(Mediator mediator, IxCoreColleague temporaryColleague, bool shouldDispose)
        {
            if (mediator == null)
            {
                throw new ArgumentNullException("'mediator' parameter cannot be null.");
            }
            if (temporaryColleague == null)
            {
                throw new ArgumentNullException("'temporaryColleague' parameter cannot be null.");
            }

            m_mediator           = mediator;
            m_temporaryColleague = temporaryColleague;
            m_shouldDispose      = shouldDispose;
        }
        //from IUIMenuAdapter
//		public ContextMenu MakeContextMenu (ChoiceGroup group)
//		{
//			CommandBarContextMenu menu= new CommandBarContextMenu();
//			menu.Tag = group;
//			group.ReferenceWidget = menu;
//			menu.Popup += new System.EventHandler(group.OnDisplay);
//
//			return (ContextMenu)menu;
//		}

        public void ShowContextMenu(ChoiceGroup group, Point location,
                                    TemporaryColleagueParameter temporaryColleagueParam,
                                    MessageSequencer sequencer)
        {
            using (CommandBarContextMenu menu = new CommandBarContextMenu())
            {
                menu.Tag = group;
                group.ReferenceWidget = menu;
                menu.Popup           += new System.EventHandler(group.OnDisplay);

                // Pre-menu process two optional paremeters.
                if (temporaryColleagueParam != null)
                {
                    temporaryColleagueParam.Mediator.AddColleague(temporaryColleagueParam.TemporaryColleague);
                }
                bool resume = false;
                if (sequencer != null)
                {
                    resume = sequencer.PauseMessageQueueing();
                }

                // NB: This is *always* modal, as it doesn't return until it closes.
                menu.Show(null, location);

                // Post-menu process two optional paremeters.s
                if (temporaryColleagueParam != null)
                {
                    IxCoreColleague colleague = temporaryColleagueParam.TemporaryColleague;
                    temporaryColleagueParam.Mediator.RemoveColleague(colleague);
                    if (temporaryColleagueParam.ShouldDispose && colleague is IDisposable)
                    {
                        (colleague as IDisposable).Dispose();
                    }
                }
                if (sequencer != null && resume)
                {
                    sequencer.ResumeMessageQueueing();
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Executes in two distinct scenarios.
        ///
        /// 1. If disposing is true, the method has been called directly
        /// or indirectly by a user's code via the Dispose method.
        /// Both managed and unmanaged resources can be disposed.
        ///
        /// 2. If disposing is false, the method has been called by the
        /// runtime from inside the finalizer and you should not reference (access)
        /// other managed objects, as they already have been garbage collected.
        /// Only unmanaged resources can be disposed.
        /// </summary>
        /// <param name="disposing"></param>
        /// <remarks>
        /// If any exceptions are thrown, that is fine.
        /// If the method is being done in a finalizer, it will be ignored.
        /// If it is thrown by client code calling Dispose,
        /// it needs to be handled by fixing the bug.
        ///
        /// If subclasses override this method, they should call the base implementation.
        /// </remarks>
        protected override void Dispose(bool disposing)
        {
            //Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************");
            // Can be called more than once, but not run more than once.
            if (m_isDisposed)
                return;

            if (disposing)
            {
                // Dispose managed resources here.

                // Use a copy of the m_colleagues Set,
                // since the Dispose methods on the colleague should remove itself from m_colleagues,
                // which will cause an exception to be throw (list changed while spinning through it.
                Set<IxCoreColleague> copyOfColleagues = new Set<IxCoreColleague>(m_colleagues.ToArray());
                m_colleagues.Clear(); // Just get rid of them now.
                foreach (IxCoreColleague icc in copyOfColleagues)
                {
                    if (icc is IDisposable)
                    {
                        // Is the class marked with [XCore.MediatorDispose],
                        // or is it in the temporary colleague holder?
                        object[] attrs = icc.GetType().GetCustomAttributes(typeof(MediatorDisposeAttribute), true);
                        if ((attrs != null && attrs.Length > 0)
                            || m_temporaryColleague == icc)
                        {
                            (icc as IDisposable).Dispose();
                        }
                    }
                }
                copyOfColleagues.Clear();
                if (m_propertyTable != null)
                    m_propertyTable.Dispose();
                if (m_commandSet != null)
                    m_commandSet.Dispose();
                if (m_pathVariables != null)
                    m_pathVariables.Clear();
                if (m_disposedColleagues != null)
                    m_disposedColleagues.Clear();
                if (m_jobs != null)
                    m_jobs.Clear();
                if (m_pendingjobs != null)
                    m_pendingjobs.Clear();
                if (m_MethodsOnAnyColleague != null)
                    m_MethodsOnAnyColleague.Clear();

                m_idleQueue.Dispose();
            }

            // Dispose unmanaged resources here, whether disposing is true or false.
            m_mainWndPtr = IntPtr.Zero;
            m_MethodsOnAnyColleague = null;
            m_pendingjobs = null;
            m_jobs = null;
            m_disposedColleagues = null;
            m_temporaryColleague = null;
            m_propertyTable = null;
            m_commandSet = null;
            m_colleagues = null;
            m_pathVariables = null;
            /* It is illegal to try to access managed stuff in this part of the Dispose method.
            #if DEBUG
            //DebugMsg("-- Number of calls to the InvokeRecursively method = " + m_invokeCount.ToString());
            DebugMsg("-- Number of saved calls to Type.GetMethod = " + m_SavedCalls.ToString());
            DebugMsg("-- Mediator MsgHash info: count=" + m_MethodsNOTonColleagues.Count + " mx depth=" + m_MethodsCount);
            DebugMsg("-- Mediator  - Calls to check for method on colleague: " + m_MethodChecks);
            #endif
            */
            m_isDisposed = true;

            base.Dispose(disposing);
        }
Beispiel #6
0
 public void RemoveColleague(IxCoreColleague colleague)
 {
     CheckDisposed();
     // No need to check if m_colleagues is null.
     // if it hasn't been dispoded, as it will always be non-null.
     // If it has been disposed, then the caller should be fixed to be better
     // behaved about calling disposed objects.  (Read: it shouldn't ever call code on disposed objects.)
     //if (m_colleagues != null)
     m_colleagues.Remove(colleague);
 }
Beispiel #7
0
        public void AddTemporaryColleague(IxCoreColleague colleague)
        {
            CheckDisposed();

            if (m_temporaryColleague != null)
                RemoveColleague(m_temporaryColleague);

            m_temporaryColleague = colleague;	// only keep one temporary colleague at a time (menu based)
            AddColleague(m_temporaryColleague);
        }
Beispiel #8
0
        public void AddColleague(IxCoreColleague colleague)
        {
            CheckDisposed();

            // Note: m_colleagues is now a Set, so would ignore the attempt to add it again.
            // The problem with that is it is really a programming error to add them more than once.
            // So, we will keep the exception.
            if (m_colleagues.Contains(colleague))
                throw new ApplicationException ("This object is already in the list of colleagues.");

            m_colleagues.Add(colleague);
        }
Beispiel #9
0
        //static System.Diagnostics.Stopwatch ttime = new Stopwatch();
        /// <summary>
        ///
        /// </summary>
        /// <param name="colleague"></param>
        /// <param name="methodName"></param>
        /// <param name="parameterTypes"></param>
        /// <param name="parameterList"></param>
        /// <param name="previous">to catch infinite loops</param>
        private bool InvokeRecursively(IxCoreColleague colleague, string methodName, Type[] parameterTypes,
			object[] parameterList, HashSet<object> previous, bool stopWhenHandled, bool justCheckingForReceivers)
        {
            if (!ProcessMessages)
                return true;

            bool handled = false;
            //			Trace.Indent();
            if (invokeSwitch.TraceVerbose)
            {
                Trace.WriteLine("InvokeRecursively: methodName=<" + methodName + "> colleague=<" + colleague.ToString() + ">", invokeSwitch.DisplayName);
            }
            m_invokeCount++;
            //////// THIS IS TESTING CODE ADDED AND COMMENTED AND NEEDS TO BE REVERTED WHEN DONE>>>>>>>>
            //////// ><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>
            ////////ttime.Start();
            ////////ttime.Stop();
            ////////if ((m_invokeCount % 1000) == 0)
            ////////{
            ////////	TimeSpan ts = ttime.Elapsed;
            ////////	string tsString = String.Format("{0:00}.{1:0000}({2})",
            ////////		ts.Seconds,	ts.Milliseconds, ts.Ticks );
            ////////	Trace.WriteLine(tsString + " ColleagueHasBeenDisposed(" + colleague.ToString() + ")="+chbDisposed.ToString());
            ////////	ttime.Reset();
            ////////}
            if (colleague.ShouldNotCall)
            {
                DebugMsg("_+_+_+_+ InvokeRecursively called on colleague that is disposed/disposing: " + colleague.ToString());
                return false;	// stop the processing
            }

            IxCoreColleague[] targets = colleague.GetMessageTargets();
            // Try following the 'Code Performance' guidelines which says that
            // .."foreach introduces both managed heap and virtual function overhead..
            // This can be a significant factor in performance-sensitive regions of your application."
            // This section of code is indeed a very performance-sensitive region!
            //
            for (int index = 0; index < targets.Length; index++) // foreach(IxCoreColleague target in targets)
            {
                if (!ProcessMessages)
                    return true;

                IxCoreColleague target = targets[index];
                if(target == null)
                {
                    //Debug.WriteLine("Warning, target null.");
                    continue;
                }

                //this section is the leaf of the search tree
                if (target == colleague)
                {
                    //Check to see whether we have encountered this target before.
                    //how can we encounter the same one twice?
                    //This will happen when more than one colleague includes some shared object as one of its children.
                    //in xWorks, this happens with the RecordClerk, which is not a top-level colleague on its own.
                    // The following is logically equivalent to
                    //if (previous.Contains(target))
                    //{
                    //	break;
                    //}
                    //previous.Add(target);
                    // but faster.
                    int oldCount = previous.Count;
                    previous.Add(target);
                    if (oldCount == previous.Count)
                        break; // it was already present, that is, we've processed it before.

                    MethodInfo mi = CheckForMatchingMessage(colleague, methodName, parameterTypes);
                    if (mi != null)
                    {
                        if (justCheckingForReceivers)
                        {
                            handled = true;
                            break;
                        }
                        else
                        {
                            if (methodName == "OnMasterRefresh")
                            {
                                InvokeMethod(target, mi, parameterList);
                                handled = true;
                            }
                            else
                            {
                                object o = InvokeMethod(target, mi, parameterList);
                                handled = (o != null) ? (bool) o : false;
                            }
                        }
                    }
                    else
                    {
                        m_SavedCalls++;
                    }
                }
                else //not at a leaf yet, keep going down the tree
                    handled = InvokeRecursively(target, methodName, parameterTypes, parameterList, previous, stopWhenHandled, justCheckingForReceivers);

                if(handled && stopWhenHandled)
                {
                    Trace.WriteLineIf(invokeSwitch.TraceVerbose, "-->handled=true And stopWhenHandled=true", invokeSwitch.DisplayName);
                    break;
                }
                else if(handled)
                    Trace.WriteLineIf(invokeSwitch.TraceVerbose, "-->handled=true", invokeSwitch.DisplayName);

            }
            //			TraceVerboseLine("}");
            //			Trace.Unindent();
            return handled;
        }
Beispiel #10
0
        private object InvokeMethod(IxCoreColleague target, MethodInfo mi, object[] parameterList)
        {
            if (!ProcessMessages)
                return null;

            try
            {
                Trace.Indent();

                if (invokeSwitch.TraceInfo)
                {
                    if (parameterList.Length > 0 && parameterList[0] != null)
                        Trace.WriteLine(" Invoking Method: " + mi.Name + "('" + parameterList[0].ToString() + "')" + " on " + target.ToString(), invokeSwitch.DisplayName);
                    else
                        Trace.WriteLine(" Invoking Method: " + mi.Name + " on " + target.ToString(), invokeSwitch.DisplayName);
                }
            #if false
                string objName = "";
                objName = target.ToString() + target.GetHashCode().ToString();
                // DLH TESTING - not finished yet...
                if (IsDisposedColleague(objName))
                {
                    Debug.WriteLine("##Not Invoking disposed object:"+objName);
                    return null;
                }
            #endif
                /// *****************************************************************************
                /// Have seen a stack situation that the Mediator has been disposed of after
                /// returning from this call - IOW's the following call allows re-entrance.
                /// That's why the exception follows to handle a known case when processing the
                /// ExitApplication msg.
                /// *****************************************************************************
                object returnValue = mi.Invoke(target, parameterList);
                if (m_isDisposed)
                    throw new DisposedInAnotherFrameException();

                if (target == m_temporaryColleague && !mi.Name.StartsWith("OnDisplay"))
                {
                    RemoveColleague(m_temporaryColleague);
                    m_temporaryColleague = null;	// only keep one temporary colleague at a time (menu based)
                }

                Trace.Unindent();

                return returnValue;
            }
                //note that we don't want to catch just any kind of the exception here,
                //most exceptions will be invoked by the method that we actually called.
                //the only exceptions we want to catch are the ones that just mean that we failed to find
                //a suitable method. These we can report if in debug-mode, otherwise ignore.
            catch(System.ArgumentException error)
            {
                //I once spent close to an hour wondering what was causing the failure here.
                //The exception message was "Object type cannot be converted to target type."
                //the answer was that I had made the signature be a UIListDisplayProperties
                //when it should have been a UIItemDisplayProperties. The two can be pretty hard to
                //distinguish visually. (John Hatton)
                Debug.Fail("The method '"+mi.Name+"' was found but couldn't be invoked. Maybe has the wrong signature?", error.Message);
            }
            //			catch(ConfigurationException error)
            //			{
            //				throw error; //already has good user notification message in it
            //			}
            //			catch(RuntimeConfigurationException error)
            //			{
            //				throw error; //already has good user notification message in it
            //			}
            catch(TargetInvocationException error)
            {
                Exception inner = error.InnerException;	//unwrap, for example, a ConfigurationException
                // See LT-1629 "Closing one db while opening another crashes".  The following
                // two lines  appear to fix this bug, although I'm not too happy about this
                // asynchronous behavior appearing where we (or at least I) don't expect it.
                // Unfortunately, that's inherent with message handling architecture when
                // handling one message allows other messages to be handled before it finishes.
                // - SteveMc
                if (inner is System.NullReferenceException &&
                    mi.Name == "OnChooseLangProject")
                {
                    // We probably closed the target's window after choosing another project,
                    // but before getting to this point in processing the ChooseLP message.  So
                    // ignore the exception.
                    return null;
                }
                string s = "Something went wrong trying to invoke "+ target.ToString() +":"+ mi.Name +"().";
                //if we just send on the error, then the caller
                //will find it more easy to trap particular kind of exceptions. On the other hand,
                //if the exception makes it all the way to the user, then we will really want to see this extra string (s)
                //at the top level.

                throw new Exception(s, inner);

                //if we were to just bring up the green box), then that makes it impossible for the caller to catch
                //the exception. In particular, the link-jumping column can fail if the object it is trying to jump to
                //has been deleted. This is really not an "error", and if we let the exception get back to the
                //jumping code, then it can notify the user more calmly.
                //SIL.Utils.ErrorReporter.ReportException(new ApplicationException(s, inner));
            }
            return null;
        }
Beispiel #11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="target"></param>
        /// <param name="methodName"></param>
        /// <param name="parameterTypes">Currently, use null here if you have a ref param</param>
        /// <param name="parameterList"></param>
        /// <returns>null or the MethodInfo if a matching one was found</returns>
        private MethodInfo CheckForMatchingMessage(IxCoreColleague target, string methodName, Type[] parameterTypes)
        {
            //NB: I did not think about these flags; I just copied them from an example
            BindingFlags flags =
                BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance;

            Type type = target.GetType();
            MethodInfo mi;
            //
            // By using the JetBrains dotTrace profiler, the addition of m_TypeMethodInfo is saving
            // a significant (>20%) amount of time by not having to make as many calls to the expensive
            // System.Type.GetMethod()
            //
            if (parameterTypes == null) // callers currently must use null here if they have a "ref" param (TODO)
            {
                Dictionary<string, MethodInfo> methodDict;
                if (m_TypeMethodInfo.TryGetValue(type, out methodDict))
                {
                    if (methodDict.TryGetValue(methodName, out mi))
                        return mi;
                }
                else
                {
                    methodDict = new Dictionary<string, MethodInfo>();
                    m_TypeMethodInfo[type] = methodDict;
                }
                mi = type.GetMethod(methodName, flags);
                methodDict[methodName] = mi;
            }
            else
            {
                var key = parameterTypes.Length + methodName; // method name could end with number, but not start.
                Dictionary<string, MethodInfo> methodDict;
                if (m_TypeMethodInfo.TryGetValue(type, out methodDict))
                {
                    if (methodDict.TryGetValue(key, out mi))
                        return mi;
                }
                else
                {
                    methodDict = new Dictionary<string, MethodInfo>();
                    m_TypeMethodInfo[type] = methodDict;
                }
                mi = type.GetMethod(methodName, flags, null, parameterTypes, null);
                methodDict[key] = mi;
            }
            return mi;
        }
Beispiel #12
0
		/// <summary>
		/// Constructor with paramters being required.
		/// </summary>
		/// <param name="mediator">Mediator that will handle the collegue during its temporary liketime.</param>
		/// <param name="temporaryColleague"></param>
		public TemporaryColleagueParameter(Mediator mediator, IxCoreColleague temporaryColleague, bool shouldDispose)
		{
			if (mediator == null)
				throw new ArgumentNullException("'mediator' parameter cannot be null.");
			if (temporaryColleague == null)
				throw new ArgumentNullException("'temporaryColleague' parameter cannot be null.");

			m_mediator = mediator;
			m_temporaryColleague = temporaryColleague;
			m_shouldDispose = shouldDispose;
		}
Beispiel #13
0
		private bool HandleRightClickOnObject(int hvoReal, IxCoreColleague additionalTarget)
		{
			Debug.Assert(Mediator != null);
			CmObjectUi rightClickUiObj = CmObjectUi.MakeUi(Cache, hvoReal);
			if (rightClickUiObj != null)
			{
				rightClickUiObj.AdditionalColleague = additionalTarget;
				m_fHandlingRightClickMenu = true;
				try
				{
					//Debug.WriteLine("hvoReal=" + hvoReal.ToString() + " " + ui.Object.ShortName + "  " + ui.Object.ToString());
					return rightClickUiObj.HandleRightClick(Mediator, this, true, CmObjectUi.MarkCtrlClickItem);
				}
				finally
				{
					m_fHandlingRightClickMenu = false;
					rightClickUiObj.Dispose();
				}
			}
			return false;
		}
Beispiel #14
0
		/// <summary>
		///
		/// </summary>
		/// <param name="target"></param>
		/// <param name="methodName"></param>
		/// <param name="parameterTypes">Currently, use null here if you have a ref param</param>
		/// <param name="parameterList"></param>
		/// <returns>null or the MethodInfo if a matching one was found</returns>
		private MethodInfo CheckForMatchingMessage(IxCoreColleague target, string methodName, Type[] parameterTypes,
			object[] parameterList, Set<int> previous)
		{
#if false
			//tostring here is too expensive to leave lying around
			Trace.Indent();
			TraceVerboseLine(" Checking : "+ target.ToString());
#endif
			int x = target.GetHashCode();
			if (previous.Contains(x))
			{
				throw new ArgumentException("XCore Mediator encountered the same " + target.ToString() + " twice on check for " + methodName + ", as if there is a loop.");
			}
#if false
			TraceVerboseLine("Adding "+target.ToString()+":"+x.ToString());
#endif
			previous.Add(x);

			//NB: I did not think about these flags; I just copied them from an example
			BindingFlags flags =
				BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance;

			Type type = target.GetType();
			MethodInfo mi;
			//
			// By using the JetBrains dotTrace profiler, the addition of m_TypeMethodInfo is saving
			// a significant (>20%) amount of time by not having to make as many calls to the expensive
			// System.Type.GetMethod()
			//
			if (parameterTypes == null) // callers currently must use null here if they have a "ref" param (TODO)
			{
				string key = type.ToString() + "_" + methodName;
				if (m_TypeMethodInfo.ContainsKey(key))
				{
					mi = m_TypeMethodInfo[key];
				}
				else
				{
					mi = type.GetMethod(methodName, flags);
					m_TypeMethodInfo[key] = mi;
				}
			}
			else
			{
				string key2 = type.ToString() + "_" + methodName + "_" + parameterTypes.Length.ToString();
				if (m_TypeMethodInfo.ContainsKey(key2))
				{
					mi = m_TypeMethodInfo[key2];
				}
				else
				{
					mi= type.GetMethod(methodName, flags, null,	parameterTypes, null);
					m_TypeMethodInfo[key2] = mi;
				}
			}
#if false
			Trace.Unindent();
#endif
			return mi;
		}
Beispiel #15
0
		private bool ColleagueHasBeenDisposed(IxCoreColleague target)
		{
			bool hasBeenDisposed = false;

			if (target is IDisposable)
			{
				// Have to use reflection to see if it has an IsDisposed property,
				// since that is not part of the interface for IDisposable for some odd reason.
				// Get the property infor for the ActiveViewHelper property on the control
				// (assuming there is one).
				PropertyInfo propInfo = target.GetType().GetProperty("IsDisposed",
					BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

				// If we successfully found an ActiveViewHelper property, then reference
				// it to set our class' active view helper member variable.
				if (propInfo != null)
				{
					hasBeenDisposed = (bool)propInfo.GetValue(target,
						BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
						null, null, null);

					if (!hasBeenDisposed)
					{
						propInfo = target.GetType().GetProperty("Disposing",
							BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

						// If we successfully found an ActiveViewHelper property, then reference
						// it to set our class' active view helper member variable.
						if (propInfo != null)
						{
							hasBeenDisposed = (bool)propInfo.GetValue(target,
								BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
								null, null, null);
						}
					}
				}
			}

			return hasBeenDisposed;
		}