protected virtual bool ShouldReverseChildren(ReverseContext context)
        {
            var currentModelNode = context.CurrentModelNode;

            // that's the root model node
            // always continue
            if (currentModelNode == null)
            {
                return(true);
            }

            // get a particular depth option for definition
            var definitionType = currentModelNode.Value.GetType();
            var depthOption    = context.ReverseOptions
                                 .Options
                                 .FirstOrDefault(o => o.DefinitionClassFullName == definitionType.FullName &&
                                                 o is ReverseDepthOption) as ReverseDepthOption;

            // does it exist? no more that suggested depth
            if (depthOption != null)
            {
                return(_localReverseDepth[definitionType] < depthOption.Depth);
            }

            // always full in, by default
            return(true);
        }
        protected virtual ReverseResult ReverseInternal(object modelHost, ReverseOptions options)
        {
            var result = new ReverseResult();

            var context = new ReverseContext
            {
                ReverseOptions = options,
                ReverseHost    = modelHost as ReverseHostBase
            };

            ReverseModel(context);

            result.Model = context.RootModelNode;

            return(result);
        }
        protected virtual ReverseResult ReverseInternal(object modelHost, ReverseOptions options)
        {
            var result = new ReverseResult();

            var context = new ReverseContext
            {
                ReverseOptions = options,
                ReverseHost = modelHost as ReverseHostBase
            };

            ReverseModel(context);

            result.Model = context.RootModelNode;

            return result;
        }
        protected virtual void ReverseModel(ReverseContext context)
        {
            if (context.RootModelNode == null)
            {
                Type rootTargetType = null;
                ModelNode modelNode = null;
                ReverseHandlerBase rootHandler = null;

                var rootHost = context.ReverseHost;

                // manually reverse a single 'root' model node
                // update RequireSelfProcessing to false 

                if (context.ReverseHost.GetType() == typeof(SiteReverseHost))
                {
                    rootTargetType = typeof(SiteDefinition);
                    rootHandler = Handlers.First(h => h.ReverseType == rootTargetType);

                    modelNode = rootHandler.ReverseSingleHost(rootHost, context.ReverseOptions);
                    modelNode.Options.RequireSelfProcessing = false;
                }
                else if (context.ReverseHost.GetType() == typeof(WebReverseHost))
                {
                    rootTargetType = typeof(WebDefinition);
                    rootHandler = Handlers.First(h => h.ReverseType == rootTargetType);

                    modelNode = rootHandler.ReverseSingleHost(rootHost, context.ReverseOptions);
                    modelNode.Options.RequireSelfProcessing = false;
                }

                context.RootModelNode = modelNode;
                context.CurrentModelNode = modelNode;

                InvokeOnReverseProgress(new ReverseProgressEventArgs
                {
                    CurrentNode = modelNode,
                    TargetType = modelNode.GetType(),
                    ProcessedModelNodeCount = 1,
                    TotalModelNodeCount = 1
                });
            }

            var defType = context.CurrentModelNode.Value.GetType();

            if (!_localReverseDepth.ContainsKey(defType))
                _localReverseDepth.Add(defType, 0);
            else
                _localReverseDepth[defType] = _localReverseDepth[defType] + 1;

            var shouldReverseSelfChildren = ShouldReverseChildren(context);

            var targetType = context.CurrentModelNode.Value.GetType();
            var childHandlers = Handlers.Where(h => h.ReverseParentTypes.Any(t => t == targetType))
                                        .ToList();

            // prevent furver reverse of the same type
            if (!shouldReverseSelfChildren)
            {
                var selfHandler = childHandlers.FirstOrDefault(h => h.ReverseType == defType);

                if (selfHandler != null)
                {
                    childHandlers.Remove(selfHandler);
                }
            }

            foreach (var handler in childHandlers)
            {
                var hosts = handler.ReverseHosts(context.ReverseHost, context.ReverseOptions);

                var count = 1;
                var totalCount = hosts.Count();

                foreach (var host in hosts)
                {
                    var modelNode = handler.ReverseSingleHost(host, context.ReverseOptions);

                    context.CurrentModelNode.ChildModels.Add(modelNode);

                    InvokeOnReverseProgress(new ReverseProgressEventArgs
                    {
                        CurrentNode = modelNode,
                        TargetType = modelNode.GetType(),
                        ProcessedModelNodeCount = count,
                        TotalModelNodeCount = totalCount
                    });

                    ReverseModel(new ReverseContext
                    {
                        ReverseOptions = context.ReverseOptions,
                        CurrentModelNode = modelNode,
                        ReverseHost = host,
                        RootModelNode = context.RootModelNode
                    });

                    count++;
                }
            }

            _localReverseDepth[defType] = _localReverseDepth[defType] - 1;
        }
        protected virtual bool ShouldReverseChildren(ReverseContext context)
        {
            var currentModelNode = context.CurrentModelNode;

            // that's the root model node
            // always continue
            if (currentModelNode == null)
                return true;

            // get a particular depth option for definition
            var definitionType = currentModelNode.Value.GetType();
            var depthOption = context.ReverseOptions
                .Options
                .FirstOrDefault(o => o.DefinitionClassFullName == definitionType.FullName
                                    && o is ReverseDepthOption) as ReverseDepthOption;

            // does it exist? no more that suggested depth
            if (depthOption != null)
            {
                return _localReverseDepth[definitionType] < depthOption.Depth;
            }

            // always full in, by default
            return true;
        }
        protected virtual void ReverseModel(ReverseContext context)
        {
            if (context.RootModelNode == null)
            {
                Type               rootTargetType = null;
                ModelNode          modelNode      = null;
                ReverseHandlerBase rootHandler    = null;

                var rootHost = context.ReverseHost;

                // manually reverse a single 'root' model node
                // update RequireSelfProcessing to false

                if (context.ReverseHost.GetType() == typeof(SiteReverseHost))
                {
                    rootTargetType = typeof(SiteDefinition);
                    rootHandler    = Handlers.First(h => h.ReverseType == rootTargetType);

                    modelNode = rootHandler.ReverseSingleHost(rootHost, context.ReverseOptions);
                    modelNode.Options.RequireSelfProcessing = false;
                }
                else if (context.ReverseHost.GetType() == typeof(WebReverseHost))
                {
                    rootTargetType = typeof(WebDefinition);
                    rootHandler    = Handlers.First(h => h.ReverseType == rootTargetType);

                    modelNode = rootHandler.ReverseSingleHost(rootHost, context.ReverseOptions);
                    modelNode.Options.RequireSelfProcessing = false;
                }

                context.RootModelNode    = modelNode;
                context.CurrentModelNode = modelNode;

                InvokeOnReverseProgress(new ReverseProgressEventArgs
                {
                    CurrentNode             = modelNode,
                    TargetType              = modelNode.GetType(),
                    ProcessedModelNodeCount = 1,
                    TotalModelNodeCount     = 1
                });
            }

            var defType = context.CurrentModelNode.Value.GetType();

            if (!_localReverseDepth.ContainsKey(defType))
            {
                _localReverseDepth.Add(defType, 0);
            }
            else
            {
                _localReverseDepth[defType] = _localReverseDepth[defType] + 1;
            }

            var shouldReverseSelfChildren = ShouldReverseChildren(context);

            var targetType    = context.CurrentModelNode.Value.GetType();
            var childHandlers = Handlers.Where(h => h.ReverseParentTypes.Any(t => t == targetType))
                                .ToList();

            // prevent furver reverse of the same type
            if (!shouldReverseSelfChildren)
            {
                var selfHandler = childHandlers.FirstOrDefault(h => h.ReverseType == defType);

                if (selfHandler != null)
                {
                    childHandlers.Remove(selfHandler);
                }
            }

            foreach (var handler in childHandlers)
            {
                var hosts = handler.ReverseHosts(context.ReverseHost, context.ReverseOptions);

                var count      = 1;
                var totalCount = hosts.Count();

                foreach (var host in hosts)
                {
                    var modelNode = handler.ReverseSingleHost(host, context.ReverseOptions);

                    context.CurrentModelNode.ChildModels.Add(modelNode);

                    InvokeOnReverseProgress(new ReverseProgressEventArgs
                    {
                        CurrentNode             = modelNode,
                        TargetType              = modelNode.GetType(),
                        ProcessedModelNodeCount = count,
                        TotalModelNodeCount     = totalCount
                    });

                    ReverseModel(new ReverseContext
                    {
                        ReverseOptions   = context.ReverseOptions,
                        CurrentModelNode = modelNode,
                        ReverseHost      = host,
                        RootModelNode    = context.RootModelNode
                    });

                    count++;
                }
            }

            _localReverseDepth[defType] = _localReverseDepth[defType] - 1;
        }