public override bool Equals(object obj)
            {
                TypeMemberDescriptor other = obj as TypeMemberDescriptor;

                return(other != null && other.Member.Equals(Member));
            }
        private CustomTypeDescriptor(Type type, bool isAnonymousClass, MemberInfo[] members, string[] names)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            //
            // No members supplied? Get all public, instance-level fields and
            // properties of the type that are not marked with the JsonIgnore
            // attribute.
            //

            if (members == null)
            {
                const BindingFlags bindings   = BindingFlags.Instance | BindingFlags.Public;
                FieldInfo[]        fields     = type.GetFields(bindings);
                PropertyInfo[]     properties = type.GetProperties(bindings);

                //
                // Filter out members marked with JsonIgnore attribute.
                //

                ArrayList memberList = new ArrayList(fields.Length + properties.Length);
                memberList.AddRange(fields);
                memberList.AddRange(properties);

                for (int i = 0; i < memberList.Count; i++)
                {
                    MemberInfo member = (MemberInfo)memberList[i];

                    if (!member.IsDefined(typeof(JsonIgnoreAttribute), true))
                    {
                        continue;
                    }

                    memberList.RemoveAt(i--);
                }

                members = (MemberInfo[])memberList.ToArray(typeof(MemberInfo));
            }

            PropertyDescriptorCollection logicalProperties = new PropertyDescriptorCollection(null);

            int index = 0;

            foreach (MemberInfo member in members)
            {
                FieldInfo            field      = member as FieldInfo;
                string               name       = names != null && index < names.Length ? names[index] : null;
                TypeMemberDescriptor descriptor = null;

                if (field != null)
                {
                    //
                    // Add public fields that are not read-only and not
                    // constant literals.
                    //

                    if (field.DeclaringType != type && field.ReflectedType != type)
                    {
                        throw new ArgumentException(null, "members");
                    }

                    if (!field.IsInitOnly && !field.IsLiteral)
                    {
                        descriptor = new TypeFieldDescriptor(field, name);
                    }
                }
                else
                {
                    PropertyInfo property = member as PropertyInfo;

                    if (property == null)
                    {
                        throw new ArgumentException(null, "members");
                    }

                    //
                    // Add public properties that can be read and modified.
                    // If property is read-only yet has the JsonExport
                    // attribute applied then include it anyhow (assuming
                    // that the type author probably has customizations
                    // that know how to deal with the sceanrio more
                    // accurately). What's more, if the type is anonymous
                    // then the rule that the proerty must be writeable is
                    // also bypassed.
                    //

                    if (property.DeclaringType != type && property.ReflectedType != type)
                    {
                        throw new ArgumentException(null, "members");
                    }

                    if ((property.CanRead) &&
                        (isAnonymousClass || property.CanWrite || property.IsDefined(typeof(JsonExportAttribute), true)) &&
                        property.GetIndexParameters().Length == 0)
                    {
                        //
                        // Properties of an anonymous class will always use
                        // their original property name so that no
                        // transformation (like auto camel-casing) is
                        // applied. The rationale for the exception here is
                        // that since the user does not have a chance to
                        // decorate properties of an anonymous class with
                        // attributes, there is no way an overriding policy
                        // can be implemented.
                        //

                        descriptor = new TypePropertyDescriptor(property,
                                                                isAnonymousClass ? Mask.EmptyString(name, property.Name) : name);
                    }
                }

                if (descriptor != null)
                {
                    descriptor.ApplyCustomizations();
                    logicalProperties.Add(descriptor);
                }

                index++;
            }

            _properties = logicalProperties;
        }