1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation. All rights reserved.
\r
5 * This software is subject to the Microsoft Public License (Ms-PL).
\r
6 * A copy of the license can be found in the license.htm file included
\r
7 * in this distribution.
\r
9 * You must not remove this notice, or any other, from this software.
\r
11 * ***************************************************************************/
\r
13 namespace System.Web.Mvc {
\r
15 using System.Collections;
\r
16 using System.Collections.Generic;
\r
17 using System.Diagnostics.CodeAnalysis;
\r
19 using System.Runtime.Serialization;
\r
22 public class TempDataDictionary : IDictionary<string, object>, ISerializable {
\r
23 internal const string _tempDataSerializationKey = "__tempData";
\r
25 private Dictionary<string, object> _data;
\r
26 private HashSet<string> _initialKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
\r
27 private HashSet<string> _retainedKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
\r
29 public TempDataDictionary() {
\r
30 _data = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
\r
33 protected TempDataDictionary(SerializationInfo info, StreamingContext context) {
\r
34 _data = info.GetValue(_tempDataSerializationKey, typeof(Dictionary<string, object>)) as Dictionary<string, object>;
\r
43 public ICollection<string> Keys {
\r
49 public void Keep() {
\r
50 _retainedKeys.Clear();
\r
51 _retainedKeys.UnionWith(_data.Keys);
\r
54 public void Keep(string key) {
\r
55 _retainedKeys.Add(key);
\r
58 public void Load(ControllerContext controllerContext, ITempDataProvider tempDataProvider) {
\r
59 IDictionary<string, object> providerDictionary = tempDataProvider.LoadTempData(controllerContext);
\r
60 _data = (providerDictionary != null) ? new Dictionary<string, object>(providerDictionary, StringComparer.OrdinalIgnoreCase) :
\r
61 new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
\r
62 _initialKeys = new HashSet<string>(_data.Keys, StringComparer.OrdinalIgnoreCase);
\r
63 _retainedKeys.Clear();
\r
66 public object Peek(string key) {
\r
68 _data.TryGetValue(key, out value);
\r
72 public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider) {
\r
73 string[] keysToKeep = _initialKeys.Union(_retainedKeys, StringComparer.OrdinalIgnoreCase).ToArray();
\r
74 string[] keysToRemove = _data.Keys.Except(keysToKeep, StringComparer.OrdinalIgnoreCase).ToArray();
\r
75 foreach (string key in keysToRemove) {
\r
78 tempDataProvider.SaveTempData(controllerContext, _data);
\r
81 public ICollection<object> Values {
\r
83 return _data.Values;
\r
87 public object this[string key] {
\r
90 if (TryGetValue(key, out value)) {
\r
91 _initialKeys.Remove(key);
\r
98 _initialKeys.Add(key);
\r
102 public void Add(string key, object value) {
\r
103 _data.Add(key, value);
\r
104 _initialKeys.Add(key);
\r
107 public void Clear() {
\r
109 _retainedKeys.Clear();
\r
110 _initialKeys.Clear();
\r
113 public bool ContainsKey(string key) {
\r
114 return _data.ContainsKey(key);
\r
117 public bool ContainsValue(object value) {
\r
118 return _data.ContainsValue(value);
\r
121 public IEnumerator<KeyValuePair<string, object>> GetEnumerator() {
\r
122 return new TempDataDictionaryEnumerator(this);
\r
125 protected virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
\r
126 info.AddValue(_tempDataSerializationKey, _data);
\r
129 public bool Remove(string key) {
\r
130 _retainedKeys.Remove(key);
\r
131 _initialKeys.Remove(key);
\r
132 return _data.Remove(key);
\r
135 public bool TryGetValue(string key, out object value) {
\r
136 _initialKeys.Remove(key);
\r
137 return _data.TryGetValue(key, out value);
\r
140 #region ICollection<KeyValuePair<string, object>> Implementation
\r
141 bool ICollection<KeyValuePair<string, object>>.IsReadOnly {
\r
143 return ((ICollection<KeyValuePair<string, object>>)_data).IsReadOnly;
\r
147 void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int index) {
\r
148 ((ICollection<KeyValuePair<string, object>>)_data).CopyTo(array, index);
\r
151 void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> keyValuePair) {
\r
152 _initialKeys.Add(keyValuePair.Key);
\r
153 ((ICollection<KeyValuePair<string, object>>)_data).Add(keyValuePair);
\r
156 bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> keyValuePair) {
\r
157 return ((ICollection<KeyValuePair<string, object>>)_data).Contains(keyValuePair);
\r
160 bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> keyValuePair) {
\r
161 _initialKeys.Remove(keyValuePair.Key);
\r
162 return ((ICollection<KeyValuePair<string, object>>)_data).Remove(keyValuePair);
\r
166 #region IEnumerable Implementation
\r
167 IEnumerator IEnumerable.GetEnumerator() {
\r
168 return (IEnumerator)(new TempDataDictionaryEnumerator(this));
\r
172 #region ISerializable Members
\r
173 [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
\r
174 void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
\r
175 GetObjectData(info, context);
\r
179 private sealed class TempDataDictionaryEnumerator : IEnumerator<KeyValuePair<string, object>> {
\r
180 private IEnumerator<KeyValuePair<string, object>> _enumerator;
\r
181 private TempDataDictionary _tempData;
\r
183 public TempDataDictionaryEnumerator(TempDataDictionary tempData) {
\r
184 _tempData = tempData;
\r
185 _enumerator = _tempData._data.GetEnumerator();
\r
188 public KeyValuePair<string, object> Current {
\r
190 KeyValuePair<string, object> kvp = _enumerator.Current;
\r
191 _tempData._initialKeys.Remove(kvp.Key);
\r
196 public bool MoveNext() {
\r
197 return _enumerator.MoveNext();
\r
200 public void Reset() {
\r
201 _enumerator.Reset();
\r
204 #region IEnumerator Implementation
\r
205 object IEnumerator.Current {
\r
212 #region IDisposable Implementation
\r
213 void IDisposable.Dispose() {
\r
214 _enumerator.Dispose();
\r