/// <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); }