private void DiscoverRecordFields(Type recordType) { if (!IsDynamicObject) // recordType != typeof(ExpandoObject)) { JSONRecordFieldConfigurations.Clear(); if (ChoTypeDescriptor.GetProperties(recordType).Where(pd => pd.Attributes.OfType <ChoJSONRecordFieldAttribute>().Any()).Any()) { foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(recordType).Where(pd => pd.Attributes.OfType <ChoJSONRecordFieldAttribute>().Any())) { var obj = new ChoJSONRecordFieldConfiguration(pd.Name, pd.Attributes.OfType <ChoJSONRecordFieldAttribute>().First()); obj.FieldType = pd.PropertyType; JSONRecordFieldConfigurations.Add(obj); } } else { foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(recordType)) { var obj = new ChoJSONRecordFieldConfiguration(pd.Name, (string)null); obj.FieldType = pd.PropertyType; JSONRecordFieldConfigurations.Add(obj); } } } }
internal ChoJSONRecordFieldConfiguration GetFieldConfiguration(string propertyName, ChoJSONRecordFieldAttribute attr = null, Attribute[] otherAttrs = null, PropertyDescriptor pd = null, string fqm = null, Type subType = null) { if (subType != null) { MapRecordFieldsForType(subType); var fc = new ChoJSONRecordFieldConfiguration(propertyName, attr, otherAttrs); fc.PropertyDescriptor = pd; fc.DeclaringMember = fqm; AddFieldForType(subType, fc); return(fc); } else { if (!JSONRecordFieldConfigurations.Any(fc => fc.Name == propertyName)) { JSONRecordFieldConfigurations.Add(new ChoJSONRecordFieldConfiguration(propertyName, attr, otherAttrs)); } var nfc = JSONRecordFieldConfigurations.First(fc => fc.Name == propertyName); nfc.PropertyDescriptor = pd; nfc.DeclaringMember = fqm; return(nfc); } }
internal ChoJSONRecordFieldConfiguration GetFieldConfiguration(string fn) { fn = fn.NTrim(); if (!JSONRecordFieldConfigurations.Any(fc => fc.Name == fn)) JSONRecordFieldConfigurations.Add(new ChoJSONRecordFieldConfiguration(fn, (string)null)); return JSONRecordFieldConfigurations.First(fc => fc.Name == fn); }
public override void Validate(object state) { if (RecordType != null) { Init(RecordType); } base.Validate(state); string[] fieldNames = null; JObject jObject = null; if (state is Tuple<long, JObject>) jObject = ((Tuple<long, JObject>)state).Item2; else fieldNames = state as string[]; if (AutoDiscoverColumns && JSONRecordFieldConfigurations.Count == 0) { if (RecordType != null && !IsDynamicObject /*&& RecordType != typeof(ExpandoObject)*/ && ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType<ChoJSONRecordFieldAttribute>().Any()).Any()) { MapRecordFields(RecordType); } else if (jObject != null) { Dictionary<string, ChoJSONRecordFieldConfiguration> dict = new Dictionary<string, ChoJSONRecordFieldConfiguration>(StringComparer.CurrentCultureIgnoreCase); string name = null; foreach (var attr in jObject.Properties()) { name = attr.Name; if (!dict.ContainsKey(name)) dict.Add(name, new ChoJSONRecordFieldConfiguration(name, (string)null)); else { throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name)); } } foreach (ChoJSONRecordFieldConfiguration obj in dict.Values) JSONRecordFieldConfigurations.Add(obj); } else if (!fieldNames.IsNullOrEmpty()) { foreach (string fn in fieldNames) { var obj = new ChoJSONRecordFieldConfiguration(fn, (string)null); JSONRecordFieldConfigurations.Add(obj); } } } else { foreach (var fc in JSONRecordFieldConfigurations) { fc.ComplexJPathUsed = !(fc.JSONPath.IsNullOrWhiteSpace() || String.Compare(fc.FieldName, fc.JSONPath, true) == 0); } } if (JSONRecordFieldConfigurations.Count <= 0) throw new ChoRecordConfigurationException("No record fields specified."); //Validate each record field foreach (var fieldConfig in JSONRecordFieldConfigurations) fieldConfig.Validate(this); //Check field position for duplicate string[] dupFields = JSONRecordFieldConfigurations.GroupBy(i => i.Name) .Where(g => g.Count() > 1) .Select(g => g.Key).ToArray(); if (dupFields.Length > 0) throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(String.Join(",", dupFields))); PIDict = new Dictionary<string, System.Reflection.PropertyInfo>(); PDDict = new Dictionary<string, PropertyDescriptor>(); foreach (var fc in JSONRecordFieldConfigurations) { if (fc.PropertyDescriptor == null) fc.PropertyDescriptor = ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Name == fc.Name).FirstOrDefault(); if (fc.PropertyDescriptor == null) continue; PIDict.Add(fc.PropertyDescriptor.Name, fc.PropertyDescriptor.ComponentType.GetProperty(fc.PropertyDescriptor.Name)); PDDict.Add(fc.PropertyDescriptor.Name, fc.PropertyDescriptor); } RecordFieldConfigurationsDict = JSONRecordFieldConfigurations.Where(i => !i.Name.IsNullOrWhiteSpace()).ToDictionary(i => i.Name); LoadNCacheMembers(JSONRecordFieldConfigurations); }
private void DiscoverRecordFields(Type recordType, string declaringMember, bool optIn = false) { if (!recordType.IsDynamicType()) { Type pt = null; if (ChoTypeDescriptor.GetProperties(recordType).Where(pd => pd.Attributes.OfType<ChoJSONRecordFieldAttribute>().Any()).Any()) { foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(recordType)) { pt = pd.PropertyType.GetUnderlyingType(); bool optIn1 = ChoTypeDescriptor.GetProperties(pt).Where(pd1 => pd1.Attributes.OfType<ChoJSONRecordFieldAttribute>().Any()).Any(); if (optIn1 && !pt.IsSimple() && !typeof(IEnumerable).IsAssignableFrom(pt) && FlatToNestedObjectSupport) { DiscoverRecordFields(pt, declaringMember == null ? pd.Name : "{0}.{1}".FormatString(declaringMember, pd.Name), optIn1); } else if (pd.Attributes.OfType<ChoJSONRecordFieldAttribute>().Any()) { var obj = new ChoJSONRecordFieldConfiguration(pd.Name, pd.Attributes.OfType<ChoJSONRecordFieldAttribute>().First(), pd.Attributes.OfType<Attribute>().ToArray()); obj.FieldType = pt; obj.PropertyDescriptor = pd; obj.DeclaringMember = declaringMember == null ? null : "{0}.{1}".FormatString(declaringMember, pd.Name); if (!JSONRecordFieldConfigurations.Any(c => c.Name == pd.Name)) JSONRecordFieldConfigurations.Add(obj); } } } else { foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(recordType)) { JsonIgnoreAttribute jiAttr = pd.Attributes.OfType<JsonIgnoreAttribute>().FirstOrDefault(); if (jiAttr != null) continue; pt = pd.PropertyType.GetUnderlyingType(); if (pt != typeof(object) && !pt.IsSimple() && !typeof(IEnumerable).IsAssignableFrom(pt) && FlatToNestedObjectSupport) { DiscoverRecordFields(pt, declaringMember == null ? pd.Name : "{0}.{1}".FormatString(declaringMember, pd.Name), optIn); } else { var obj = new ChoJSONRecordFieldConfiguration(pd.Name, (string)null); obj.FieldType = pt; obj.PropertyDescriptor = pd; obj.DeclaringMember = declaringMember == null ? null : "{0}.{1}".FormatString(declaringMember, pd.Name); StringLengthAttribute slAttr = pd.Attributes.OfType<StringLengthAttribute>().FirstOrDefault(); if (slAttr != null && slAttr.MaximumLength > 0) obj.Size = slAttr.MaximumLength; ChoUseJSONSerializationAttribute sAttr = pd.Attributes.OfType<ChoUseJSONSerializationAttribute>().FirstOrDefault(); if (sAttr != null) obj.UseJSONSerialization = true; JsonPropertyAttribute jAttr = pd.Attributes.OfType<JsonPropertyAttribute>().FirstOrDefault(); if (jAttr != null && !jAttr.PropertyName.IsNullOrWhiteSpace()) { obj.FieldName = jAttr.PropertyName; } else { DisplayAttribute dpAttr = pd.Attributes.OfType<DisplayAttribute>().FirstOrDefault(); if (dpAttr != null) { if (!dpAttr.ShortName.IsNullOrWhiteSpace()) obj.FieldName = dpAttr.ShortName; else if (!dpAttr.Name.IsNullOrWhiteSpace()) obj.FieldName = dpAttr.Name; } } DisplayFormatAttribute dfAttr = pd.Attributes.OfType<DisplayFormatAttribute>().FirstOrDefault(); if (dfAttr != null && !dfAttr.DataFormatString.IsNullOrWhiteSpace()) { obj.FormatText = dfAttr.DataFormatString; } if (dfAttr != null && !dfAttr.NullDisplayText.IsNullOrWhiteSpace()) { obj.NullValue = dfAttr.NullDisplayText; } if (!JSONRecordFieldConfigurations.Any(c => c.Name == pd.Name)) JSONRecordFieldConfigurations.Add(obj); } } } } }
internal void WithField(string name, string jsonPath = null, Type fieldType = null, ChoFieldValueTrimOption fieldValueTrimOption = ChoFieldValueTrimOption.Trim, string fieldName = null, Func <object, object> valueConverter = null, Func <object, object> itemConverter = null, Func <object, object> customSerializer = null, object defaultValue = null, object fallbackValue = null, string fullyQualifiedMemberName = null, string formatText = null, bool?isArray = null, string nullValue = null, Type recordType = null, Type subRecordType = null, Func <JObject, Type> fieldTypeSelector = null) { ChoGuard.ArgumentNotNull(recordType, nameof(recordType)); if (!name.IsNullOrEmpty()) { if (subRecordType != null) { MapRecordFieldsForType(subRecordType); } string fnTrim = fieldName.IsNullOrWhiteSpace() ? name.NTrim() : fieldName; ChoJSONRecordFieldConfiguration fc = null; PropertyDescriptor pd = null; if (JSONRecordFieldConfigurations.Any(o => o.FieldName == fnTrim)) { fc = JSONRecordFieldConfigurations.Where(o => o.FieldName == fnTrim).First(); JSONRecordFieldConfigurations.Remove(fc); pd = ChoTypeDescriptor.GetNestedProperty(recordType, fullyQualifiedMemberName.IsNullOrWhiteSpace() ? name : fullyQualifiedMemberName); } else if (subRecordType != null) { pd = ChoTypeDescriptor.GetNestedProperty(subRecordType, fullyQualifiedMemberName.IsNullOrWhiteSpace() ? name : fullyQualifiedMemberName); } else { pd = ChoTypeDescriptor.GetNestedProperty(recordType, fullyQualifiedMemberName.IsNullOrWhiteSpace() ? name : fullyQualifiedMemberName); } var nfc = new ChoJSONRecordFieldConfiguration(fnTrim, pd != null ? ChoTypeDescriptor.GetPropetyAttribute <ChoJSONRecordFieldAttribute>(pd) : null, pd != null ? pd.Attributes.OfType <Attribute>().ToArray() : null) { }; nfc.JSONPath = !jsonPath.IsNullOrWhiteSpace() ? jsonPath : nfc.JSONPath; nfc.FieldType = fieldType != null ? fieldType : nfc.FieldType; nfc.FieldValueTrimOption = fieldValueTrimOption; nfc.FieldName = fieldName.IsNullOrWhiteSpace() ? (name.IsNullOrWhiteSpace() ? nfc.FieldName : name) : fieldName; nfc.ValueConverter = valueConverter != null ? valueConverter : nfc.ValueConverter; nfc.CustomSerializer = customSerializer != null ? customSerializer : nfc.CustomSerializer; nfc.DefaultValue = defaultValue != null ? defaultValue : nfc.DefaultValue; nfc.FallbackValue = fallbackValue != null ? fallbackValue : nfc.FallbackValue; nfc.FormatText = !formatText.IsNullOrWhiteSpace() ? formatText : nfc.FormatText; nfc.ItemConverter = itemConverter != null ? itemConverter : nfc.ItemConverter; nfc.IsArray = isArray != null ? isArray : nfc.IsArray; nfc.NullValue = !nullValue.IsNullOrWhiteSpace() ? nullValue : nfc.NullValue; nfc.FieldTypeSelector = fieldTypeSelector != null ? fieldTypeSelector : nfc.FieldTypeSelector; if (fullyQualifiedMemberName.IsNullOrWhiteSpace()) { nfc.PropertyDescriptor = fc != null ? fc.PropertyDescriptor : pd; nfc.DeclaringMember = fc != null ? fc.DeclaringMember : fullyQualifiedMemberName; } else { if (subRecordType == null) { pd = ChoTypeDescriptor.GetNestedProperty(recordType, fullyQualifiedMemberName); } else { pd = ChoTypeDescriptor.GetNestedProperty(subRecordType, fullyQualifiedMemberName); } nfc.PropertyDescriptor = pd; nfc.DeclaringMember = fullyQualifiedMemberName; } if (pd != null) { if (nfc.FieldType == null) { nfc.FieldType = pd.PropertyType; } } if (subRecordType == null) { JSONRecordFieldConfigurations.Add(nfc); } else { AddFieldForType(subRecordType, nfc); } } }
public override void Validate(object state) { if (TurnOnAutoDiscoverJsonConverters) { ChoJSONConvertersCache.Init(); } if (_jsonSerializerSettings != null) { foreach (var conv in GetJSONConverters()) { _jsonSerializerSettings.Converters.Add(conv); } foreach (var conv in _jsonSerializerSettings.Converters.OfType <IChoJSONConverter>()) { conv.Serializer = JsonSerializer; conv.Context = new ChoDynamicObject(); conv.Context.Configuration = this; } foreach (var conv in _jsonSerializerSettings.Converters) { JsonSerializer.Converters.Add(conv); } } if (RecordType != null) { Init(RecordType); } base.Validate(state); string[] fieldNames = null; JObject jObject = null; if (state is Tuple <long, JObject> ) { jObject = ((Tuple <long, JObject>)state).Item2; } else { fieldNames = state as string[]; } if (fieldNames != null && JSONRecordFieldConfigurations.Count > 0 && FlattenNode) { JSONRecordFieldConfigurations.Clear(); } if (AutoDiscoverColumns && JSONRecordFieldConfigurations.Count == 0) { if (RecordType != null && !IsDynamicObject && /*&& RecordType != typeof(ExpandoObject)*/ ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType <ChoJSONRecordFieldAttribute>().Any()).Any()) { MapRecordFields(RecordType); } else if (jObject != null) { Dictionary <string, ChoJSONRecordFieldConfiguration> dict = new Dictionary <string, ChoJSONRecordFieldConfiguration>(StringComparer.CurrentCultureIgnoreCase); string name = null; foreach (var attr in jObject.Properties()) { name = attr.Name; if (!dict.ContainsKey(name)) { dict.Add(name, new ChoJSONRecordFieldConfiguration(name, (string)null)); } else { throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name)); } } foreach (ChoJSONRecordFieldConfiguration obj in dict.Values) { JSONRecordFieldConfigurations.Add(obj); } } else if (!fieldNames.IsNullOrEmpty()) { foreach (string fn in fieldNames) { if (IgnoredFields.Contains(fn)) { continue; } var obj = new ChoJSONRecordFieldConfiguration(fn, (string)null); JSONRecordFieldConfigurations.Add(obj); } } } else { foreach (var fc in JSONRecordFieldConfigurations) { fc.ComplexJPathUsed = !(fc.JSONPath.IsNullOrWhiteSpace() || String.Compare(fc.FieldName, fc.JSONPath, true) == 0); } } //if (JSONRecordFieldConfigurations.Count <= 0) // throw new ChoRecordConfigurationException("No record fields specified."); //Validate each record field foreach (var fieldConfig in JSONRecordFieldConfigurations) { fieldConfig.Validate(this); } //Check field position for duplicate string[] dupFields = JSONRecordFieldConfigurations.GroupBy(i => i.FieldName) .Where(g => g.Count() > 1) .Select(g => g.Key).ToArray(); if (dupFields.Length > 0) { throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(String.Join(",", dupFields))); } PIDict = new Dictionary <string, System.Reflection.PropertyInfo>(StringComparer.InvariantCultureIgnoreCase); PDDict = new Dictionary <string, PropertyDescriptor>(StringComparer.InvariantCultureIgnoreCase); foreach (var fc in JSONRecordFieldConfigurations) { var pd1 = fc.DeclaringMember.IsNullOrWhiteSpace() ? ChoTypeDescriptor.GetProperty(RecordType, fc.Name) : ChoTypeDescriptor.GetProperty(RecordType, fc.DeclaringMember); if (pd1 != null) { fc.PropertyDescriptor = pd1; } if (fc.PropertyDescriptor == null) { fc.PropertyDescriptor = TypeDescriptor.GetProperties(RecordType).AsTypedEnumerable <PropertyDescriptor>().Where(pd => pd.Name == fc.Name).FirstOrDefault(); } if (fc.PropertyDescriptor == null) { continue; } PIDict.Add(fc.Name, fc.PropertyDescriptor.ComponentType.GetProperty(fc.PropertyDescriptor.Name)); PDDict.Add(fc.Name, fc.PropertyDescriptor); } RecordFieldConfigurationsDict = JSONRecordFieldConfigurations.Where(i => !i.Name.IsNullOrWhiteSpace()).ToDictionary(i => i.Name); LoadNCacheMembers(JSONRecordFieldConfigurations); }
internal void WithField(string name, string jsonPath = null, Type fieldType = null, ChoFieldValueTrimOption fieldValueTrimOption = ChoFieldValueTrimOption.Trim, string fieldName = null, Func <object, object> valueConverter = null, Func <object, object> itemConverter = null, Func <object, object> customSerializer = null, object defaultValue = null, object fallbackValue = null, string fullyQualifiedMemberName = null, string formatText = null, bool isArray = true, string nullValue = null, Type recordType = null, Type subRecordType = null, Func <JObject, Type> fieldTypeSelector = null) { ChoGuard.ArgumentNotNull(recordType, nameof(recordType)); if (!name.IsNullOrEmpty()) { if (subRecordType != null) { MapRecordFieldsForType(subRecordType); } string fnTrim = name.NTrim(); ChoJSONRecordFieldConfiguration fc = null; PropertyDescriptor pd = null; if (JSONRecordFieldConfigurations.Any(o => o.Name == fnTrim)) { fc = JSONRecordFieldConfigurations.Where(o => o.Name == fnTrim).First(); JSONRecordFieldConfigurations.Remove(fc); } else if (subRecordType != null) { pd = ChoTypeDescriptor.GetNestedProperty(subRecordType, fullyQualifiedMemberName.IsNullOrWhiteSpace() ? name : fullyQualifiedMemberName); } else { pd = ChoTypeDescriptor.GetNestedProperty(recordType, fullyQualifiedMemberName.IsNullOrWhiteSpace() ? name : fullyQualifiedMemberName); } var nfc = new ChoJSONRecordFieldConfiguration(fnTrim, jsonPath) { FieldType = fieldType, FieldValueTrimOption = fieldValueTrimOption, FieldName = fieldName.IsNullOrWhiteSpace() ? name : fieldName, ValueConverter = valueConverter, CustomSerializer = customSerializer, DefaultValue = defaultValue, FallbackValue = fallbackValue, FormatText = formatText, ItemConverter = itemConverter, IsArray = isArray, NullValue = nullValue, FieldTypeSelector = fieldTypeSelector, }; if (fullyQualifiedMemberName.IsNullOrWhiteSpace()) { nfc.PropertyDescriptor = fc != null ? fc.PropertyDescriptor : pd; nfc.DeclaringMember = fc != null ? fc.DeclaringMember : fullyQualifiedMemberName; } else { if (subRecordType == null) { pd = ChoTypeDescriptor.GetNestedProperty(recordType, fullyQualifiedMemberName); } else { pd = ChoTypeDescriptor.GetNestedProperty(subRecordType, fullyQualifiedMemberName); } nfc.PropertyDescriptor = pd; nfc.DeclaringMember = fullyQualifiedMemberName; } if (pd != null) { if (nfc.FieldType == null) { nfc.FieldType = pd.PropertyType; } } if (subRecordType == null) { JSONRecordFieldConfigurations.Add(nfc); } else { AddFieldForType(subRecordType, nfc); } } }
public override void Validate(object state) { base.Validate(state); string[] fieldNames = null; JObject jObject = null; if (state is Tuple <long, JObject> ) { jObject = ((Tuple <long, JObject>)state).Item2; } else { fieldNames = state as string[]; } if (AutoDiscoverColumns && JSONRecordFieldConfigurations.Count == 0) { if (RecordType != null && !IsDynamicObject && /*&& RecordType != typeof(ExpandoObject)*/ ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType <ChoJSONRecordFieldAttribute>().Any()).Any()) { long startIndex = 0; long size = 0; string jpath = null; ChoJSONRecordFieldAttribute attr = null; foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType <ChoJSONRecordFieldAttribute>().Any())) { attr = ChoTypeDescriptor.GetPropetyAttribute <ChoJSONRecordFieldAttribute>(pd); var obj = new ChoJSONRecordFieldConfiguration(pd.Name, jpath); obj.FieldType = pd.PropertyType; JSONRecordFieldConfigurations.Add(obj); startIndex += size; } } else if (jObject != null) { Dictionary <string, ChoJSONRecordFieldConfiguration> dict = new Dictionary <string, ChoJSONRecordFieldConfiguration>(StringComparer.CurrentCultureIgnoreCase); string name = null; foreach (var attr in jObject.Properties()) { name = attr.Name; if (!dict.ContainsKey(name)) { dict.Add(name, new ChoJSONRecordFieldConfiguration(name, (string)null)); } else { throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name)); } } foreach (ChoJSONRecordFieldConfiguration obj in dict.Values) { JSONRecordFieldConfigurations.Add(obj); } } else if (!fieldNames.IsNullOrEmpty()) { foreach (string fn in fieldNames) { var obj = new ChoJSONRecordFieldConfiguration(fn, (string)null); JSONRecordFieldConfigurations.Add(obj); } } } else { foreach (var fc in JSONRecordFieldConfigurations) { fc.ComplexJPathUsed = !(fc.JSONPath.IsNullOrWhiteSpace() || String.Compare(fc.FieldName, fc.JSONPath, true) == 0); } } if (JSONRecordFieldConfigurations.Count <= 0) { throw new ChoRecordConfigurationException("No record fields specified."); } //Validate each record field foreach (var fieldConfig in JSONRecordFieldConfigurations) { fieldConfig.Validate(this); } //Check field position for duplicate string[] dupFields = JSONRecordFieldConfigurations.GroupBy(i => i.Name) .Where(g => g.Count() > 1) .Select(g => g.Key).ToArray(); if (dupFields.Length > 0) { throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(String.Join(",", dupFields))); } RecordFieldConfigurationsDict = JSONRecordFieldConfigurations.Where(i => !i.Name.IsNullOrWhiteSpace()).ToDictionary(i => i.Name); LoadNCacheMembers(JSONRecordFieldConfigurations); }
private void DiscoverRecordFields(Type recordType, string declaringMember = null, bool optIn = false) { if (!IsDynamicObject) // recordType != typeof(ExpandoObject)) { Type pt = null; if (optIn) //ChoTypeDescriptor.GetProperties(recordType).Where(pd => pd.Attributes.OfType<ChoJSONRecordFieldAttribute>().Any()).Any()) { foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(recordType)) { pt = pd.PropertyType.GetUnderlyingType(); if (!pt.IsSimple() && !typeof(IEnumerable).IsAssignableFrom(pt)) { DiscoverRecordFields(pt, declaringMember == null ? pd.Name : "{0}.{1}".FormatString(declaringMember, pd.Name), optIn); } else if (pd.Attributes.OfType <ChoJSONRecordFieldAttribute>().Any()) { var obj = new ChoJSONRecordFieldConfiguration(pd.Name, pd.Attributes.OfType <ChoJSONRecordFieldAttribute>().First(), pd.Attributes.OfType <Attribute>().ToArray()); obj.FieldType = pt; obj.PropertyDescriptor = pd; obj.DeclaringMember = declaringMember == null ? null : "{0}.{1}".FormatString(declaringMember, pd.Name); JSONRecordFieldConfigurations.Add(obj); } } } else { foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(recordType)) { pt = pd.PropertyType.GetUnderlyingType(); if (!pt.IsSimple() && !typeof(IEnumerable).IsAssignableFrom(pt)) { DiscoverRecordFields(pt, declaringMember == null ? pd.Name : "{0}.{1}".FormatString(declaringMember, pd.Name), optIn); } else { var obj = new ChoJSONRecordFieldConfiguration(pd.Name, (string)null); obj.FieldType = pt; obj.PropertyDescriptor = pd; obj.DeclaringMember = declaringMember == null ? null : "{0}.{1}".FormatString(declaringMember, pd.Name); StringLengthAttribute slAttr = pd.Attributes.OfType <StringLengthAttribute>().FirstOrDefault(); if (slAttr != null && slAttr.MaximumLength > 0) { obj.Size = slAttr.MaximumLength; } DisplayAttribute dpAttr = pd.Attributes.OfType <DisplayAttribute>().FirstOrDefault(); if (dpAttr != null) { if (!dpAttr.ShortName.IsNullOrWhiteSpace()) { obj.FieldName = dpAttr.ShortName; } else if (!dpAttr.Name.IsNullOrWhiteSpace()) { obj.FieldName = dpAttr.Name; } } JSONRecordFieldConfigurations.Add(obj); } } } } }