private static void TestEquals(MethodInfo constructor, InterestingValueFactory valueFactory, Action<object, object, bool, string> verify)
        {
            var parameters = constructor.GetParameters();
            var aparams = new object[parameters.Length];
            var bparams = new object[parameters.Length];
            var usedInEquals = new bool[parameters.Length];

            for (int i = 0; i < parameters.Length; i++)
            {
                var p = parameters[i];
                if (p.ParameterType.IsSubclassOf(typeof(UsedInEquals)))
                {
                    usedInEquals[i] = true;
                }
                else if (p.ParameterType.IsSubclassOf(typeof(NotUsedInEquals)))
                {
                    usedInEquals[i] = false;
                }
                else
                {
                    throw new InvalidCastException("Ambiguous typing, could not determine if type is used in equals check or not.");
                }

                var caster = p.ParameterType.GetMethod("op_Implicit");
                var boxedType = p.ParameterType.GetGenericArguments()[0];

                aparams[i] = caster.Invoke(null, new[] { valueFactory.A(boxedType) });
                bparams[i] = caster.Invoke(null, new[] { valueFactory.B(boxedType) });
            }
            //Interesting values generated
            object allAs = constructor.Invoke(null, aparams); //use the all a's for equality checks

            var current = new object[parameters.Length];
            aparams.CopyTo(current, 0);

            var isA = new bool[parameters.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                isA[i] = true;
            }

            //Test all a's scenario

            var objUnderTest = constructor.Invoke(null, current);
            verify(objUnderTest, allAs, true, string.Join("",isA.Select(x=>x?"A":"B")));

            for (int j = 0; j < parameters.Length; j++)
            {
                current[j] = aparams[j];
                isA[j] = true;

                for (int i = j; i < parameters.Length; i++) // toggle ever parameter remaining
                {
                    current[i] = bparams[i];
                    isA[i] = false;
                    objUnderTest = constructor.Invoke(null, current);
                    bool shouldBeEqual = ShouldBeEqual(isA, usedInEquals); //if no critical params have changed
                    verify(objUnderTest, allAs, shouldBeEqual, string.Join("", isA.Select(x => x ? "A" : "B")));

                    current[i] = aparams[i];
                    isA[i] = true;
                }

                current[j] = bparams[j];
                isA[j] = false;
            }

        }
 public static void TestGetHashCode(MethodInfo constructor, InterestingValueFactory valueFactory)
 {
     TestEquals(constructor, valueFactory, TestHashCodeForSingleCase);
 }