Example #1
0
        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));
        }