1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
|
//------------------------------------------------------------------------------
// <copyright file="PersonalizationStateInfoCollection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.UI.WebControls.WebParts {
using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Util;
[Serializable]
public sealed class PersonalizationStateInfoCollection : ICollection {
private Dictionary<Key, int> _indices;
private bool _readOnly;
// Tried to use the generic type List<T> instead, but it's readonly
// implementation returns a different type that is not assignable to List<T>.
// That would require to maintain two different fields, one for the readonly
// collection when set and one for the modifiable collection version.
//
// So, the cleaner solution is to use ArrayList, though it might have a
// slightly slower perf because of explicit casting.
private ArrayList _values;
public PersonalizationStateInfoCollection() {
_indices = new Dictionary<Key, int>(KeyComparer.Default);
_values = new ArrayList();
}
public int Count {
get {
return _values.Count;
}
}
public PersonalizationStateInfo this[string path, string username] {
get {
if (path == null) {
throw new ArgumentNullException("path");
}
Key key = new Key(path, username);
int index;
if (!_indices.TryGetValue(key, out index)) {
return null;
}
return (PersonalizationStateInfo) _values[index];
}
}
public PersonalizationStateInfo this[int index] {
get {
return (PersonalizationStateInfo) _values[index];
}
}
public void Add(PersonalizationStateInfo data) {
if (data == null) {
throw new ArgumentNullException("data");
}
Key key;
UserPersonalizationStateInfo userData = data as UserPersonalizationStateInfo;
if (userData != null) {
key = new Key(userData.Path, userData.Username);
}
else {
key = new Key(data.Path, null);
}
// VSWhidbey 376063: avoid key duplicate, we check here first before we add.
if (_indices.ContainsKey(key)) {
if (userData != null) {
throw new ArgumentException(SR.GetString(SR.PersonalizationStateInfoCollection_CouldNotAddUserStateInfo,
key.Path, key.Username));
}
else {
throw new ArgumentException(SR.GetString(SR.PersonalizationStateInfoCollection_CouldNotAddSharedStateInfo,
key.Path));
}
}
int pos = _values.Add(data);
try {
_indices.Add(key, pos);
}
catch {
// Roll back the first addition to make the whole addition atomic
_values.RemoveAt(pos);
throw;
}
}
public void Clear() {
_values.Clear();
_indices.Clear();
}
public void CopyTo(PersonalizationStateInfo[] array, int index) {
_values.CopyTo(array, index);
}
public IEnumerator GetEnumerator() {
return _values.GetEnumerator();
}
public bool IsSynchronized {
get {
return false;
}
}
public void Remove(string path, string username) {
if (path == null) {
throw new ArgumentNullException("path");
}
Key key = new Key(path, username);
int ipos;
if (!_indices.TryGetValue(key, out ipos)) {
return;
}
Debug.Assert(ipos >= 0 && ipos < _values.Count);
_indices.Remove(key);
try {
_values.RemoveAt(ipos);
}
catch {
// Roll back the first addition to make the whole addition atomic
_indices.Add(key, ipos);
throw;
}
// Readjust the values' indices by -1 where the indices are greater than the removed index
ArrayList al = new ArrayList();
foreach(KeyValuePair<Key,int> de in _indices) {
if (de.Value > ipos) {
al.Add(de.Key);
}
}
foreach (Key k in al) {
_indices[k] = ((int) _indices[k]) - 1;
}
}
public void SetReadOnly() {
if (_readOnly) {
return;
}
_readOnly = true;
_values = ArrayList.ReadOnly(_values);
}
public object SyncRoot {
get {
return this;
}
}
void ICollection.CopyTo(Array array, int index) {
_values.CopyTo(array, index);
}
[Serializable]
private sealed class Key {
public string Path;
public string Username;
internal Key(string path, string username) {
Debug.Assert(path != null);
Path = path;
Username = username;
}
}
[Serializable]
private sealed class KeyComparer : IEqualityComparer<Key> {
internal static readonly IEqualityComparer<Key> Default = new KeyComparer();
bool IEqualityComparer<Key>.Equals(Key x, Key y) {
return (Compare(x, y) == 0);
}
int IEqualityComparer<Key>.GetHashCode(Key key) {
if (key == null) {
return 0;
}
Debug.Assert(key.Path != null);
int pathHashCode = key.Path.ToLowerInvariant().GetHashCode();
int usernameHashCode = 0;
if (key.Username != null) {
usernameHashCode = key.Username.ToLowerInvariant().GetHashCode();
}
return HashCodeCombiner.CombineHashCodes(pathHashCode, usernameHashCode);
}
private int Compare(Key x, Key y) {
if (x == null && y == null) {
return 0;
}
if (x == null) {
return -1;
}
if (y == null) {
return 1;
}
int pathDiff = String.Compare(x.Path, y.Path,
StringComparison.OrdinalIgnoreCase);
if (pathDiff != 0) {
return pathDiff;
}
else {
return String.Compare(x.Username, y.Username,
StringComparison.OrdinalIgnoreCase);
}
}
}
}
}
|