static KVValue ConvertObjectToValue(Type objectType, object managedObject, IObjectReflector reflector, HashSet <object> visitedObjects) { if (!objectType.IsValueType && objectType != typeof(string) && !visitedObjects.Add(managedObject)) { throw new KeyValueException("Serialization failed - circular object reference detected."); } if (TryConvertValueTo <string>(managedObject, out var convertedString)) { return(convertedString); } var childObjects = new KVCollectionValue(); if (typeof(IDictionary).IsAssignableFrom(objectType)) { var dictionary = (IDictionary)managedObject; var enumerator = dictionary.GetEnumerator(); while (enumerator.MoveNext()) { var entry = enumerator.Entry; var childObjectValue = ConvertObjectToValue(entry.Value.GetType(), entry.Value, reflector, visitedObjects); childObjects.Add(new KVObject(entry.Key.ToString(), childObjectValue)); } } else if (objectType.IsArray || typeof(IEnumerable).IsAssignableFrom(objectType)) { var counter = 0; foreach (var child in (IEnumerable)managedObject) { var childKVObject = CopyObject(child, counter.ToString(), reflector, visitedObjects); childObjects.Add(childKVObject); counter++; } } else { foreach (var member in reflector.GetMembers(managedObject).OrderBy(p => p.Name, StringComparer.InvariantCulture)) { if (!member.MemberType.IsValueType && member.Value is null) { continue; } if (TryConvertValueTo <string>(member.Value, out var convertedMemberValue)) { childObjects.Add(new KVObject(member.Name, convertedMemberValue)); } else { childObjects.Add(CopyObject(member.Value, member.Name, reflector, visitedObjects)); } } } return(childObjects); }
/// <summary> /// Initializes a new instance of the <see cref="KVObject"/> class. /// </summary> /// <param name="name">Name of this object.</param> /// <param name="items">Child items of this object.</param> public KVObject(string name, IEnumerable <KVObject> items) { Require.NotNull(name, nameof(name)); Require.NotNull(items, nameof(items)); Name = name; var value = new KVCollectionValue(); value.AddRange(items); Value = value; }