/// <summary>
        /// Dynamically Invokes either a constructor, instance or static method as supplied with the
        /// provided arguments an instance as appropriate.
        /// </summary>
        /// <param name = "method">The method to invoke.</param>
        /// <param name = "parameters">The parameters to use.</param>
        /// <param name = "instance">The instance to invoke the method against if it is an instance method.</param>
        /// <returns>The results of the instance invocation.</returns>
        private static object InternalDynaInvoke(MethodBase method, object[] parameters, object instance = null)
        {
            try
            {
                if (typeof(ConstructorInfo).IsAssignableFrom(method.GetType()))
                {
                    return(method.As <ConstructorInfo>().Invoke(parameters));
                }

                if (instance.IsNotNull() && method.IsStatic)
                {
                    return(method.Invoke(null, TestHelp.Array(instance).Union(parameters).ToArray()));
                }
                else
                {
                    return(method.Invoke(instance, parameters));
                }
            }
            catch (TargetInvocationException ex)
            {
                // An exception occurring inside of the Target when Invoked via
                // reflection will get caught and rethrown as a TargetInvocationException
                // In these cases we want to have the inner exception sent up the
                // stack so that the actual exception is presented to the test case.
                // This code removes the TargetInvocationException and "fixes" the
                // call stack to match.

                // Use reflections to get the inner field that holds the stack inside
                // of an exception.
                FieldInfo remoteStackTrace = typeof(Exception).GetField("_remoteStackTraceString", BindingFlags.Instance | BindingFlags.NonPublic);

                // Set the InnerException._remoteStackTraceString
                // to the current InnerException.StackTrace
                // This "fixes" the stack trace so that it does not appear to originate
                // from here when we re-throw the inner exception.
                remoteStackTrace.SetValue(ex.InnerException, ex.InnerException.StackTrace + Environment.NewLine);

                // Re-throw the inner exception.
                throw ex.InnerException;
            }
        }
        private static int CompareTypeAssignments(ParameterInfo[] parameters, object[] values, Type nullType, Type[] typeParameters)
        {
            TestHelp.DoNothing(typeParameters);

            int paramCount = parameters != null?parameters.Count() : 0;

            int objCount = values != null?values.Count() : 0;

            if (paramCount == 0 && objCount == 0)
            {
                return(int.MaxValue);
            }

            int           max             = Math.Max(paramCount, objCount);
            int           retval          = 0;
            ParameterInfo paramsParameter = null;

            for (int i = 0; i < max; i++)
            {
                if (i < paramCount && i < objCount)
                {
                    ParameterInfo info = parameters[i];
                    if (info.GetCustomAttributes(true).Where(a => a.GetType().IsAssignableFrom(typeof(ParamArrayAttribute))).Count() > 0)
                    {
                        paramsParameter = info;
                    }

                    Type infoType = info.ParameterType;

                    object obj     = values[i];
                    Type   objType = nullType;

                    if (obj != null)
                    {
                        objType = obj.GetType();
                    }

                    // If the object type is exactly the same as the infoType we have an exact match.
                    if (objType == infoType)
                    {
                        retval += 6;
                        continue;
                    }

                    // Check to see if method parameter is of type T.
                    if (infoType.IsGenericParameter)
                    {
                        Type[] genericParameterConstraints = infoType.GetGenericParameterConstraints();

                        if (genericParameterConstraints.Count() == 0 ||
                            genericParameterConstraints.Any(constraint => constraint.IsAssignableFrom(objType)))
                        {
                            retval += 3;
                        }
                    }
                    else if (infoType.IsArray && objType.IsArray)
                    {
                        Type infoElementType = infoType.GetElementType();
                        Type objElementType  = objType.GetElementType();
                        if (infoElementType.ContainsGenericParameters)
                        {
                            Type[] genericParameterConstraints = infoElementType.GetGenericParameterConstraints();

                            if (genericParameterConstraints.Count() == 0 ||
                                genericParameterConstraints.Any(constraint => constraint.IsAssignableFrom(objElementType)))
                            {
                                retval += 3;
                            }
                        }
                    }
                    else if (infoType.IsArray && paramsParameter.IsNotNull())
                    {
                        Type infoElementType = infoType.GetElementType();
                        Type objElementType  = objType;
                        if (infoElementType.ContainsGenericParameters)
                        {
                            Type[] genericParameterConstraints = infoElementType.GetGenericParameterConstraints();

                            if (genericParameterConstraints.Count() == 0 ||
                                genericParameterConstraints.Any(constraint => constraint.IsAssignableFrom(objElementType)))
                            {
                                retval += 3;
                            }
                        }
                    }
                    else
                    {
                        if (infoType == objType)
                        {
                            retval += 6;
                        }
                        else if (infoType.IsAssignableFrom(objType))
                        {
                            retval += 5;
                        }
                        else if (objType.IsAssignableFrom(infoType))
                        {
                            retval += 5;
                        }
                        else if (infoType.ContainsGenericParameters)
                        {
                            // Above check to see if method parameter is of type C<T>/C<U,V>.

                            // Since infoType is obtained from compile time information
                            // it does not have T resolved. Hence we use infoType.Name
                            // which is in format C'1.
                            // infoType.FullName is empty therefore it is not used.
                            if (infoType.Name == objType.Name)
                            {
                                retval += 3;
                            }
                        }
                        else if (typeof(IEnumerable).IsAssignableFrom(infoType) && typeof(IEnumerable).IsAssignableFrom(objType))
                        {
                            retval += 1;
                        }
                    }
                }
                else if (i >= paramCount && i < objCount && paramsParameter.IsNotNull())
                {
                    // params function, this method could be covered by the params array.
                    break;
                }
                else
                {
                    // parameter count is unequal so return the lowest score.
                    retval = 0;
                    break;
                }
            }

            return(retval);
        }