Example #1
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;
        }
Example #2
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;
		}