public IEnumerable <JsonMapBase[]> GetSubpathes(Type objectType) { JsonMapsTreeNode rootNode; if (!this.dictionary.TryGetValue(objectType, out rootNode) || rootNode.Children.Count == 0) { yield break; } Stack <JsonMapBase> list = new Stack <JsonMapBase>(20); Stack <Queue <JsonMapsTreeNode> > stack = new Stack <Queue <JsonMapsTreeNode> >(20); JsonMapsTreeNode node = rootNode; stack.Push(new Queue <JsonMapsTreeNode>(node.Children.Select(ct => this.dictionary[ct]))); while (true) { Queue <JsonMapsTreeNode> currentLevel = stack.Peek(); if (currentLevel.Count > 0) { node = currentLevel.Dequeue(); stack.Push(new Queue <JsonMapsTreeNode>(node.Children.Select(ct => this.dictionary[ct]))); list.Push(node.Mapper); } else { stack.Pop(); if (stack.Count == 0) { yield break; } if (list.Peek().CanCreateNew()) { yield return(list.ToArray()); } list.Pop(); } } }
private JsonMapsTree GetJsonMapsTree() { var dictionary = new Dictionary <Type, JsonMapsTreeNode>(); foreach (JsonMapBase jsonMapBase in this.maps) { Type current = jsonMapBase.SerializedType; JsonMapsTreeNode node; if (!dictionary.TryGetValue(current, out node)) { List <JsonMapBase> acceptedMaps = this.maps .Where(x => x.AcceptsType(current)) .Where(x => x.SerializedType.GetTypeInfo().IsAssignableFrom(current.GetTypeInfo())) .WithMax(x => - TypeDistance(x.SerializedType, current)) .ToList(); if (acceptedMaps.Count == 0) { throw new Exception($"`No maps for the type `{current.Name}`"); } if (acceptedMaps.Count > 1) { throw new Exception($"Ambiguous maps for the type `{current.Name}`"); } Type parent = null; Type?baseTypeInfo = current.GetTypeInfo().BaseType; if (baseTypeInfo != null) { List <JsonMapBase> acceptedParentMaps = this.maps .Where(x => x.AcceptsType(baseTypeInfo)) .Where(x => x.SerializedType.GetTypeInfo().IsAssignableFrom(baseTypeInfo.GetTypeInfo())) .WithMax(x => - TypeDistance(x.SerializedType, baseTypeInfo)) .ToList(); if (acceptedParentMaps.Count > 1) { throw new Exception($"Ambiguous maps for the type `{current.GetTypeInfo().BaseType?.Name}`"); } if (acceptedParentMaps.Count > 0 && jsonMapBase is JsonMap) { throw new Exception($"Sub mappers must be subclasses of `{typeof(JsonSubclassMap).Name}`: `{jsonMapBase.GetType().Name}`"); } if (acceptedParentMaps.Count > 0) { parent = acceptedParentMaps[0].SerializedType; } } List <JsonMapBase> acceptedChildMaps = this.maps .Where(x => current.GetTypeInfo().IsAssignableFrom(x.SerializedType.GetTypeInfo())) .Where(x => TypeDistance(current, x.SerializedType) == 1) .ToList(); Type[] children = acceptedChildMaps.Select(x => x.SerializedType).ToArray(); if (jsonMapBase is IAndSubtypes && children.Length > 0) { throw new Exception($"IAndSubtypes mapper does not accept child mappers."); } dictionary[current] = node = new JsonMapsTreeNode(jsonMapBase, parent, children); } } return(new JsonMapsTree(dictionary)); }