private void BaseRemove(Object key, bool throwIfMissing) {
if (IsReadOnly())
throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only));
int index = 0;
bool foundEntry = false;
foreach (Entry entry in _items) {
if (CompareKeys(key, entry.GetKey(this))) {
foundEntry = true;
if (entry._value == null) // A phoney delete is already present
{
if (throwIfMissing) {
throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found, key));
}
else {
return;
}
}
if (entry._value.LockItem == true) {
throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_attribute_locked, key));
}
if (entry._value.ElementPresent == false) {
CheckLockedElement(_removeElement, null); // has remove been locked?
}
switch (entry._entryType) {
case EntryType.Added:
if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
if (index >= Count - _inheritedCount) {
throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items)));
}
}
if (CollectionType == ConfigurationElementCollectionType.BasicMap) {
if (index < _inheritedCount) {
throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items)));
}
}
_items.RemoveAt(index);
}
else {
// don't really remove it from the collection just mark it removed
entry._entryType = EntryType.Removed;
_removedItemCount++;
}
break;
case EntryType.Removed:
if (throwIfMissing) {
throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_removed));
}
break;
default:
if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_elements_may_not_be_removed));
}
entry._entryType = EntryType.Removed;
_removedItemCount++;
break;
}
bModified = true;
return;
}
index++;
}
// Note because it is possible for removes to get orphaned by the API they will
// not cause a throw from the base classes. The scenerio is:
// Add an item in a parent level
// remove the item in a child level
// remove the item at the parent level.
//
// throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found));
if (foundEntry == false) {
if (throwIfMissing) {
throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found, key));
}
if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
_items.Insert(Count + _removedItemCount - _inheritedCount, new Entry(EntryType.Removed, key, null));
}
else {
_items.Add(new Entry(EntryType.Removed, key, null));
}
_removedItemCount++;
}
}
}