Ejemplo n.º 1
0
        protected virtual void Traverse <TContext>(IObjectDescriptor value, IObjectGraphVisitor <TContext> visitor, int currentDepth, TContext context)
        {
            if (++currentDepth > maxRecursion)
            {
                throw new InvalidOperationException("Too much recursion when traversing the object graph");
            }
            if (visitor.Enter(value, context))
            {
                TypeCode typeCode = value.Type.GetTypeCode();
                switch (typeCode)
                {
                case TypeCode.Boolean:
                case TypeCode.Char:
                case TypeCode.SByte:
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Int64:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                case TypeCode.DateTime:
                case TypeCode.String:
                    visitor.VisitScalar(value, context);
                    break;

                case TypeCode.Empty:
                    throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "TypeCode.{0} is not supported.", typeCode));

                default:
                    if (value.IsDbNull())
                    {
                        visitor.VisitScalar((IObjectDescriptor) new ObjectDescriptor(null, typeof(object), typeof(object)), context);
                    }
                    if (value.Value == null || value.Type == typeof(TimeSpan))
                    {
                        visitor.VisitScalar(value, context);
                    }
                    else
                    {
                        Type underlyingType = Nullable.GetUnderlyingType(value.Type);
                        if (underlyingType != null)
                        {
                            Traverse(new ObjectDescriptor(value.Value, underlyingType, value.Type, value.ScalarStyle), visitor, currentDepth, context);
                        }
                        else
                        {
                            TraverseObject(value, visitor, currentDepth, context);
                        }
                    }
                    break;
                }
            }
        }
Ejemplo n.º 2
0
        protected virtual void Traverse <TContext>(object name, IObjectDescriptor value, IObjectGraphVisitor <TContext> visitor, TContext context, Stack <ObjectPathSegment> path)
        {
            if (path.Count >= maxRecursion)
            {
                var message = new StringBuilder();
                message.AppendLine("Too much recursion when traversing the object graph.");
                message.AppendLine("The path to reach this recursion was:");

                var lines         = new Stack <KeyValuePair <string, string> >(path.Count);
                var maxNameLength = 0;
                foreach (var segment in path)
                {
                    var segmentName = TypeConverter.ChangeType <string>(segment.name);
                    maxNameLength = Math.Max(maxNameLength, segmentName.Length);
                    lines.Push(new KeyValuePair <string, string>(segmentName, segment.value.Type.FullName));
                }

                foreach (var line in lines)
                {
                    message
                    .Append(" -> ")
                    .Append(line.Key.PadRight(maxNameLength))
                    .Append("  [")
                    .Append(line.Value)
                    .AppendLine("]");
                }

                throw new MaximumRecursionLevelReachedException(message.ToString());
            }

            if (!visitor.Enter(value, context))
            {
                return;
            }

            path.Push(new ObjectPathSegment(name, value));
            try
            {
                var typeCode = value.Type.GetTypeCode();
                switch (typeCode)
                {
                case TypeCode.Boolean:
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                case TypeCode.String:
                case TypeCode.Char:
                case TypeCode.DateTime:
                    visitor.VisitScalar(value, context);
                    break;

                case TypeCode.Empty:
                    throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "TypeCode.{0} is not supported.", typeCode));

                default:
                    if (value.IsDbNull())
                    {
                        visitor.VisitScalar(new ObjectDescriptor(null, typeof(object), typeof(object)), context);
                    }

                    if (value.Value == null || value.Type == typeof(TimeSpan))
                    {
                        visitor.VisitScalar(value, context);
                        break;
                    }

                    var underlyingType = Nullable.GetUnderlyingType(value.Type);
                    if (underlyingType != null)
                    {
                        // This is a nullable type, recursively handle it with its underlying type.
                        // Note that if it contains null, the condition above already took care of it
                        Traverse("Value", new ObjectDescriptor(value.Value, underlyingType, value.Type, value.ScalarStyle), visitor, context, path);
                    }
                    else
                    {
                        TraverseObject(value, visitor, context, path);
                    }
                    break;
                }
            }
            finally
            {
                path.Pop();
            }
        }