private static void InnerSerialize(object obj, StringBuilder sb, string keyPrefix = null) { if (obj == null) { sb.AppendLine($"{keyPrefix ?? "value"} = "); return; } var type = obj.GetType(); if (TypeIsSimple(type)) { sb.AppendLine($"{keyPrefix ?? "value"} = " + obj); } else if (IsSimpleDictionary(type)) { foreach (var(key, value) in DictionaryInspector.EnumerateSimpleDictionary(obj)) { InnerSerialize(value, sb, keyPrefix == null ? key : $"{keyPrefix}.{key}"); } } else if (obj is IEnumerable) { InnerSerialize(null, sb, keyPrefix); } else if (HasCustomToString(type)) { InnerSerialize(obj.ToString(), sb, keyPrefix); } else if (HasPublicProperties(type)) { foreach (var(key, value) in ObjectPropertiesExtractor.ExtractProperties(obj)) { InnerSerialize(value, sb, keyPrefix == null ? key : $"{keyPrefix}.{key}"); } } else { sb.AppendLine($"{keyPrefix ?? "value"} = " + obj); } }
private static IPrintToken CreateInternal([CanBeNull] object item, [NotNull] HashSet <object> path, [NotNull] PrintSettings settings) { if (item == null) { return(NullValue); } if (!path.Add(item)) { return(CyclicValue); } try { var itemType = item.GetType(); using (SecurityHelper.StartSecurityScope(itemType)) { if (ToStringDetector.HasCustomToString(itemType)) { return(new ValueToken(item.ToString())); } if (CustomFormatters.TryFormat(item, out var customFormatting)) { return(new ValueToken(customFormatting)); } if (DictionaryInspector.IsSimpleDictionary(itemType)) { var pairs = DictionaryInspector.EnumerateSimpleDictionary(item); var tokens = pairs.Select(pair => new PropertyToken(pair.Item1, CreateInternal(pair.Item2, path, settings))).ToArray(); if (tokens.Length == 0) { return(EmptyObjectValue); } return(new ObjectToken(tokens)); } if (item is IEnumerable sequence) { if (!sequence.GetEnumerator().MoveNext()) { return(EmptySequenceValue); } var tokens = new List <IPrintToken>(); foreach (var element in sequence) { tokens.Add(CreateInternal(element, path, settings)); } return(new SequenceToken(tokens)); } var fieldsAndProperties = new List <PropertyToken>(); foreach (var field in itemType.GetInstanceFields()) { fieldsAndProperties.Add(ConstructProperty(field, () => CreateInternal(field.GetValue(item), path, settings), settings)); } foreach (var property in itemType.GetInstanceProperties()) { fieldsAndProperties.Add(ConstructProperty(property, () => CreateInternal(property.GetValue(item), path, settings), settings)); } if (fieldsAndProperties.Count == 0) { return(EmptyObjectValue); } return(new ObjectToken(fieldsAndProperties)); } } finally { path.Remove(item); } }
private static ISettingsNode ParseObject([CanBeNull] string name, [CanBeNull] object item, [NotNull] HashSet <object> path, [NotNull] ObjectSourceSettings settings) { if (item == null) { return(new ValueNode(name, null)); } if (!path.Add(item)) { throw new ArgumentException("Object has cyclic dependency."); } try { var itemType = item.GetType(); if (CustomFormatters.TryFormat(item, out var customFormatting)) { return(new ValueNode(name, customFormatting)); } if (ParseMethodFinder.HasAnyKindOfParseMethod(itemType) && ToStringDetector.TryInvokeCustomToString(itemType, item, out var asString)) { return(new ValueNode(name, asString)); } if (DictionaryInspector.IsSimpleDictionary(itemType)) { return(ParseDictionary(name, DictionaryInspector.EnumerateSimpleDictionary(item), path, settings)); } if (item is IEnumerable sequence) { return(ParseEnumerable(name, sequence, path, settings)); } var fieldsAndProperties = new List <ISettingsNode>(); foreach (var field in itemType.GetInstanceFields()) { var fieldValue = field.GetValue(item); if (fieldValue != null || !settings.IgnoreFieldsWithNullValue) { fieldsAndProperties.Add(ParseObject(field.Name, fieldValue, path, settings)); } } foreach (var property in itemType.GetInstanceProperties()) { var propertyValue = property.GetValue(item); if (propertyValue != null || !settings.IgnoreFieldsWithNullValue) { fieldsAndProperties.Add(ParseObject(property.Name, propertyValue, path, settings)); } } return(new ObjectNode(name, fieldsAndProperties)); } finally { path.Remove(item); } }
private static bool IsSimpleDictionary(Type type) => DictionaryInspector.IsSimpleDictionary(type);