| File: System\ComponentModel\Design\Serialization\ContextStack.cs | Web Access |
| Project: src\runtime\src\libraries\System.ComponentModel.TypeConverter\src\System.ComponentModel.TypeConverter.csproj (System.ComponentModel.TypeConverter) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; namespace System.ComponentModel.Design.Serialization { /// <summary> /// A context stack is an object that can be used by serializers /// to push various context objects. Serialization is often /// a deeply nested operation, involving many different /// serialization classes. These classes often need additional /// context information when performing serialization. As /// an example, an object with a property named "Enabled" may have /// a data type of System.Boolean. If a serializer is writing /// this value to a data stream it may want to know what property /// it is writing. It won't have this information, however, because /// it is only instructed to write the boolean value. In this /// case the parent serializer may push a PropertyDescriptor /// pointing to the "Enabled" property on the context stack. /// What objects get pushed on this stack are up to the /// individual serializer objects. /// </summary> public sealed class ContextStack { private List<object>? _contextStack; /// <summary> /// Retrieves the current object on the stack, or null /// if no objects have been pushed. /// </summary> public object? Current { get { if (_contextStack != null && _contextStack.Count > 0) { return _contextStack[_contextStack.Count - 1]; } return null; } } /// <summary> /// Retrieves the object on the stack at the given /// level, or null if no object exists at that level. /// </summary> public object? this[int level] { get { ArgumentOutOfRangeException.ThrowIfNegative(level); if (_contextStack != null && level < _contextStack.Count) { return _contextStack[_contextStack.Count - 1 - level]; } return null; } } /// <summary> /// Retrieves the first object on the stack that /// inherits from or implements the given type, or /// null if no object on the stack implements the type. /// </summary> public object? this[Type type] { get { ArgumentNullException.ThrowIfNull(type); if (_contextStack != null) { int level = _contextStack.Count; while (level > 0) { object value = _contextStack[--level]!; if (type.IsInstanceOfType(value)) { return value; } } } return null; } } /// <summary> /// Appends an object to the end of the stack, rather than pushing it /// onto the top of the stack. This method allows a serializer to communicate /// with other serializers by adding contextual data that does not have to /// be popped in order. There is no way to remove an object that was /// appended to the end of the stack without popping all other objects. /// </summary> public void Append(object context) { ArgumentNullException.ThrowIfNull(context); _contextStack ??= new List<object>(); _contextStack.Insert(0, context); } /// <summary> /// Pops the current object off of the stack, returning /// its value. /// </summary> public object? Pop() { object? context = null; if (_contextStack != null && _contextStack.Count > 0) { int idx = _contextStack.Count - 1; context = _contextStack[idx]; _contextStack.RemoveAt(idx); } return context; } /// <summary> /// Pushes the given object onto the stack. /// </summary> public void Push(object context) { ArgumentNullException.ThrowIfNull(context); _contextStack ??= new List<object>(); _contextStack.Add(context); } } }