1 //------------------------------------------------------------------------------ 2 // <copyright file="ContextStack.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 //------------------------------------------------------------------------------ 6 7 namespace System.ComponentModel.Design.Serialization { 8 9 using System; 10 using System.Collections; 11 using System.Security.Permissions; 12 13 /// <devdoc> 14 /// A context stack is an object that can be used by serializers 15 /// to push various context objects. Serialization is often 16 /// a deeply nested operation, involving many different 17 /// serialization classes. These classes often need additional 18 /// context information when performing serialization. As 19 /// an example, an object with a property named "Enabled" may have 20 /// a data type of System.Boolean. If a serializer is writing 21 /// this value to a data stream it may want to know what property 22 /// it is writing. It won't have this information, however, because 23 /// it is only instructed to write the boolean value. In this 24 /// case the parent serializer may push a PropertyDescriptor 25 /// pointing to the "Enabled" property on the context stack. 26 /// What objects get pushed on this stack are up to the 27 /// individual serializer objects. 28 /// </devdoc> 29 [HostProtection(SharedState = true)] 30 [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")] 31 public sealed class ContextStack { 32 private ArrayList contextStack; 33 34 /// <devdoc> 35 /// Retrieves the current object on the stack, or null 36 /// if no objects have been pushed. 37 /// </devdoc> 38 public object Current { 39 get { 40 if (contextStack != null && contextStack.Count > 0) { 41 return contextStack[contextStack.Count - 1]; 42 } 43 return null; 44 } 45 } 46 47 /// <devdoc> 48 /// Retrieves the object on the stack at the given 49 /// level, or null if no object exists at that level. 50 /// </devdoc> 51 public object this[int level] { 52 get { 53 if (level < 0) { 54 throw new ArgumentOutOfRangeException("level"); 55 } 56 if (contextStack != null && level < contextStack.Count) { 57 return contextStack[contextStack.Count - 1 - level]; 58 } 59 return null; 60 } 61 } 62 63 /// <devdoc> 64 /// Retrieves the first object on the stack that 65 /// inherits from or implements the given type, or 66 /// null if no object on the stack implements the type. 67 /// </devdoc> 68 public object this[Type type] { 69 get { 70 if (type == null) { 71 throw new ArgumentNullException("type"); 72 } 73 74 if (contextStack != null) { 75 int level = contextStack.Count; 76 while(level > 0) { 77 object value = contextStack[--level]; 78 if (type.IsInstanceOfType(value)) { 79 return value; 80 } 81 } 82 } 83 84 return null; 85 } 86 } 87 88 /// <devdoc> 89 /// Appends an object to the end of the stack, rather than pushing it 90 /// onto the top of the stack. This method allows a serializer to communicate 91 /// with other serializers by adding contextual data that does not have to 92 /// be popped in order. There is no way to remove an object that was 93 /// appended to the end of the stack without popping all other objects. 94 /// </devdoc> Append(object context)95 public void Append(object context) { 96 if (context == null) { 97 throw new ArgumentNullException("context"); 98 } 99 100 if (contextStack == null) { 101 contextStack = new ArrayList(); 102 } 103 contextStack.Insert(0, context); 104 } 105 106 /// <devdoc> 107 /// Pops the current object off of the stack, returning 108 /// its value. 109 /// </devdoc> Pop()110 public object Pop() { 111 object context = null; 112 113 if (contextStack != null && contextStack.Count > 0) { 114 int idx = contextStack.Count - 1; 115 context = contextStack[idx]; 116 contextStack.RemoveAt(idx); 117 } 118 119 return context; 120 } 121 122 /// <devdoc> 123 /// Pushes the given object onto the stack. 124 /// </devdoc> Push(object context)125 public void Push(object context) { 126 if (context == null) { 127 throw new ArgumentNullException("context"); 128 } 129 130 if (contextStack == null) { 131 contextStack = new ArrayList(); 132 } 133 contextStack.Add(context); 134 } 135 } 136 } 137 138