Пример #1
0
        /// <summary>
        /// Notifies that the visitor entered a node.
        /// </summary>
        /// <param name="type">The type of node the visitor entered.</param>
        /// <returns>True if this call has pushed a value to <see cref="EnteredTypes"/>, False otherwise.</returns>
        /// <remarks>The value returned by this method should be passed to the corresponding call to <see cref="LeaveNode"/>.</remarks>
        public bool EnterNode(Type type)
        {
            // EnterNode should not be called from inside a part that should be serialized as a reference - this will also fail if calls to LeaveNode are missing.
            if (SerializeAsReference)
            {
                throw new InvalidOperationException("EnterNode invoked inside a node that should be serialized as a reference.");
            }

            // Is this a referenceable type?
            var typeAttribute = References.FirstOrDefault(x => x.ReferenceableType.IsAssignableFrom(type));

            if (typeAttribute != null)
            {
                // What is the last referenceable type we entered? (serialized as-is instead of referenced)
                var lastEntered = EnteredTypes.Count > 0 ? EnteredTypes.Peek() : null;

                // It is a container for the type we're evaluating?
                if (lastEntered != null && !lastEntered.ContainedTypes.Any(x => x.IsAssignableFrom(type)))
                {
                    // Otherwise, serialize a reference to this object instead.
                    SerializeAsReference = true;
                }

                EnteredTypes.Push(typeAttribute);
                return(true);
            }
            return(false);
        }