/// <summary>
        /// Add a method to the object, will remove the previously set method if there is one. Generates a randomized return object based on the type
        /// </summary>
        /// <param name="methodName">The method to mock</param>
        /// <param name="expectedReturnType">The return type to simulate</param>
        private void UpsertMethod(string methodName, Type expectedReturnType)
        {
            Func <object> del;

            if (expectedReturnType.IsClass && expectedReturnType != typeof(string))
            {
                del = () => RandomDataGenerator.GenerateRawTestValueForClass(expectedReturnType);
            }
            else
            {
                del = () => RandomDataGenerator.GenerateRawTestValue(expectedReturnType);
            }

            if (MockedMembers.ContainsKey(methodName))
            {
                MockedMembers.Remove(methodName);
            }

            MockedMembers.Add(methodName, del);
        }
        /// <summary>
        /// Add a method to the object, will remove the previously set method if there is one. Returns the initial value set
        /// </summary>
        /// <param name="methodName">The method to mock</param>
        /// <param name="returnValue">The actual value to return</param>
        private void UpsertMethod(string methodName, object returnValue, Dictionary <string, object> outParams)
        {
            Func <object> del = () => returnValue;

            if (MockedMembers.ContainsKey(methodName))
            {
                MockedMembers.Remove(methodName);
            }

            //Always remove them if we're overloading an existing mock
            if (OutParameters.ContainsKey(methodName))
            {
                OutParameters.Remove(methodName);
            }

            //Only add this if there are any to bother with
            if (outParams.Any())
            {
                OutParameters.Add(methodName, outParams);
            }

            MockedMembers.Add(methodName, del);
        }
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var methodKeyName = binder.Name;
            var baseMethod    = BaseType.GetMethod(binder.Name);

            result = null;

            //Do we meet all the conditions outlined for this method
            if (Conditions.Any(cond => cond.Item1.Equals(methodKeyName)))
            {
                var method = BaseType.GetMethods().First(m => m.Name.Equals(methodKeyName));

                if (method != null)
                {
                    var parameters = method.GetParameters();

                    int metConditions = 0;
                    for (int i = 0; i < parameters.Count(); i++)
                    {
                        var argument = parameters.ElementAt(i);
                        var value    = args[i];

                        foreach (var condition in Conditions.Where(cond => cond.Item1.Equals(methodKeyName) && cond.Item2.Equals(argument.Name, StringComparison.OrdinalIgnoreCase)))
                        {
                            if (condition.Item3(value))
                            {
                                metConditions++;
                            }
                        }
                    }

                    if (metConditions.Equals(Conditions.Count(cond => cond.Item1.Equals(methodKeyName))))
                    {
                        //We have a match
                        methodKeyName = string.Format("{0}_{1}", binder.Name, Serialization.GenerateHashKey(Conditions.Where(cond => cond.Item1.Equals(methodKeyName)).ToArray()));
                    }
                }
            }

            //Do we want to throw an error?
            if (ExpectedErrors.Any(x => methodKeyName.Equals(x.Item1)))
            {
                Exception instance = (Exception)Activator.CreateInstance(ExpectedErrors.First(x => methodKeyName.Equals(x.Item1)).Item2);

                throw instance;
            }

            //Do we exist in the list of naked or conditional-hash-appended methods
            if (MockedMembers.ContainsKey(methodKeyName) && MockedMembers[methodKeyName] is Delegate)
            {
                Delegate del = MockedMembers[methodKeyName] as Delegate;

                result = del.DynamicInvoke();

                //Try and set out parameters
                if (OutParameters.ContainsKey(methodKeyName) && baseMethod.GetParameters().Any(param => param.IsOut))
                {
                    var outValues = OutParameters[methodKeyName];

                    int i = -1;
                    foreach (var param in baseMethod.GetParameters())
                    {
                        i++;

                        if (!param.IsOut || !outValues.ContainsKey(param.Name))
                        {
                            continue;
                        }

                        args[i] = (object)outValues[param.Name];
                    }
                }

                return(true);
            }

            //We don't exist in the list at all just try to call the base method
            return(base.TryInvokeMember(binder, args, out result));
        }