public TestModelEqualityDelegate GetEqualityTester(Type type)
        {
            var tags = DesignUtil.GetClassDesignTags(type, false);

            var equatable = typeof(IEquatable <>).MakeGenericType(type);

            if (equatable.IsAssignableFrom(type))
            {
                // horray, friendly type here
                var methodInfo = equatable.GetMethod("Equals");
                return((scope, t, expected, actual) =>
                {
                    Enforce.That(t == type);
                    bool result;
                    if (TryReferenceCheck(scope, expected, actual, out result))
                    {
                        return result;
                    }
                    return TestGenericEquality(scope, methodInfo, expected, actual);
                });
            }

            if (tags.Contains(FieldTag))
            {
                var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);

                return((scope, t, expected, actual) =>
                {
                    Enforce.That(t == type);
                    bool result;
                    if (TryReferenceCheck(scope, expected, actual, out result))
                    {
                        return result;
                    }
                    return TestFieldEquality(scope, expected, actual, fields);
                });
            }

            if (tags.Contains(PropertyTag))
            {
                var props = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                return((scope, t, expected, actual) =>
                {
                    Enforce.That(t == type);
                    bool result;
                    if (TryReferenceCheck(scope, expected, actual, out result))
                    {
                        return result;
                    }
                    return TestPropertyEquality(scope, expected, actual, props);
                });
            }

            if (typeof(ICollection).IsAssignableFrom(type))
            {
                return((scope, t, expected, actual) =>
                {
                    bool result;
                    if (TryReferenceCheck(scope, expected, actual, out result))
                    {
                        return result;
                    }
                    var first = (ICollection)expected;
                    var second = (ICollection)actual;
                    return TestCollectionEquality(scope, first, second, first.Count, second.Count);
                });
            }
            if ((type.IsGenericType) && (type.GetGenericTypeDefinition() == typeof(ICollection <>)))
            {
                //var elementType = type.GetGenericArguments()[0];
                var count = type.GetProperty("Count");

                return((scope, t, expected, actual) =>
                {
                    bool result;
                    if (TryReferenceCheck(scope, expected, actual, out result))
                    {
                        return result;
                    }
                    var firstCount = Convert.ToInt32(count.GetValue(expected, null));
                    var secondCount = Convert.ToInt32(count.GetValue(actual, null));
                    return TestCollectionEquality(scope, (IEnumerable)expected, (IEnumerable)actual, firstCount, secondCount);
                });
            }


            return((scope1, t, one1, two1) => TestSimpleEquality(scope1, one1, two1));
        }