Generic equality checker
I took a shot at this as well. I think @Hangy had a few good ideas but ended up with a rather complex solution. I haven't added any caching so you might want to add that yourself afterwards.

What I changed: 


Different check for null which is clearer in my opinion.
Braces for one-line statements.
Extracted member parsing to a separate method.
Instead of holding all data of PropertyInfo and FieldInfo, I simply use a Dictionary&lt;string, object&gt; which translates to &lt;FieldName, FieldValue&gt;.
Unused properties and fields data is eligible for GC as soon as you extracted the needed information.
Got rid of the Enumerator and added some juicy LINQ.


The end result:

public static class EqualityAttribute
{
    public static bool AreEquals&lt;T&gt;(T source, object obj) where T : class
    {
        if (ReferenceEquals(source, obj))
        {
            return true;
        }

        var convertedTarget = obj as T;
        if (convertedTarget == null)
        {
            return false;
        }

        var obj1Members = GetFieldEqualityMembers(source);
        var obj2Members = GetFieldEqualityMembers(obj);

        var noMembersToCompare = obj1Members.Values.Count == 0 &amp;&amp; obj2Members.Values.Count == 0;
        if (noMembersToCompare)
        {
            return false;
        }

        if (obj1Members.Keys.Any(key =&gt; !obj1Members[key].Equals(obj2Members[key])))
        {
            return false;
        }

        return true;
    }

    private static Dictionary&lt;string, object&gt; GetFieldEqualityMembers&lt;T&gt;(T obj)
    {
        var properties = obj.GetType().GetProperties(BindingFlags.Public |
                                                     BindingFlags.NonPublic |
                                                     BindingFlags.Instance)
            .Where(x =&gt; x.GetCustomAttribute&lt;EqualityMemberAttribute&gt;() != null)
            .ToDictionary(x =&gt; x.Name, x =&gt; x.GetValue(obj));

        var fields = obj.GetType().GetFields(BindingFlags.Public |
                                             BindingFlags.NonPublic |
                                             BindingFlags.Instance)
            .Where(x =&gt; x.GetCustomAttribute&lt;EqualityMemberAttribute&gt;() != null)
            .ToDictionary(x =&gt; x.Name, x =&gt; x.GetValue(obj));

        properties.ToList().ForEach(x =&gt; fields.Add(x.Key, x.Value));
        return fields;
    }
}