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; }
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; }