protected internal override void Unmerge(ConfigurationElement sourceElement,
ConfigurationElement parentElement,
ConfigurationSaveMode saveMode) {
base.Unmerge(sourceElement, parentElement, saveMode);
if (sourceElement != null) {
ConfigurationElementCollection parentCollection = parentElement as ConfigurationElementCollection;
ConfigurationElementCollection sourceCollection = sourceElement as ConfigurationElementCollection;
Hashtable Inheritance = new Hashtable();
_lockedAllExceptAttributesList = sourceElement._lockedAllExceptAttributesList;
_lockedAllExceptElementsList = sourceElement._lockedAllExceptElementsList;
_fItemLocked = sourceElement._fItemLocked;
_lockedAttributesList = sourceElement._lockedAttributesList;
_lockedElementsList = sourceElement._lockedElementsList;
AssociateContext(sourceElement._configRecord);
if (parentElement != null) {
if (parentElement._lockedAttributesList != null)
_lockedAttributesList = UnMergeLockList(sourceElement._lockedAttributesList,
parentElement._lockedAttributesList, saveMode);
if (parentElement._lockedElementsList != null)
_lockedElementsList = UnMergeLockList(sourceElement._lockedElementsList,
parentElement._lockedElementsList, saveMode);
if (parentElement._lockedAllExceptAttributesList != null)
_lockedAllExceptAttributesList = UnMergeLockList(sourceElement._lockedAllExceptAttributesList,
parentElement._lockedAllExceptAttributesList, saveMode);
if (parentElement._lockedAllExceptElementsList != null)
_lockedAllExceptElementsList = UnMergeLockList(sourceElement._lockedAllExceptElementsList,
parentElement._lockedAllExceptElementsList, saveMode);
}
if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
// When writing out portable configurations the <clear/> tag should be written
bCollectionCleared = sourceCollection.bCollectionCleared;
EmitClear = (saveMode == ConfigurationSaveMode.Full && (_clearElement.Length != 0)) ||
(saveMode == ConfigurationSaveMode.Modified && bCollectionCleared) ?
true : sourceCollection.EmitClear;
if ((parentCollection != null) && (EmitClear != true)) {
foreach (Entry entry in parentCollection.Items) {
if (entry._entryType != EntryType.Removed) {
Inheritance[entry.GetKey(this)] = InheritedType.inParent;
}
}
}
foreach (Entry entry in sourceCollection.Items) {
if (entry._entryType != EntryType.Removed) {
if (Inheritance.Contains(entry.GetKey(this))) {
Entry parentEntry = (Entry)parentCollection.Items[parentCollection.RealIndexOf(entry._value)];
ConfigurationElement elem = entry._value;
if (elem.Equals(parentEntry._value)) {
Inheritance[entry.GetKey(this)] = InheritedType.inBothSame;
if (saveMode == ConfigurationSaveMode.Modified) {
if (elem.IsModified()) {
Inheritance[entry.GetKey(this)] = InheritedType.inBothDiff;
} else
if (elem.ElementPresent) {
// This is when the source file contained the entry but it was an
// exact copy. We don't want to emit a remove so we treat it as
// a special case.
Inheritance[entry.GetKey(this)] = InheritedType.inBothCopyNoRemove;
}
}
}
else {
Inheritance[entry.GetKey(this)] = InheritedType.inBothDiff;
if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate
&& entry._entryType == EntryType.Added) {
// this is a special case for deailing with defect number 529517
// this code allow the config to write out the same xml when no remove was
// present during deserialization.
Inheritance[entry.GetKey(this)] = InheritedType.inBothCopyNoRemove;
}
}
}
else { // not in parent
Inheritance[entry.GetKey(this)] = InheritedType.inSelf;
}
}
}
//
if ((parentCollection != null) && (EmitClear != true)) {
foreach (Entry entry in parentCollection.Items) {
if (entry._entryType != EntryType.Removed) {
InheritedType tp = (InheritedType)Inheritance[entry.GetKey(this)];
if (tp == InheritedType.inParent || tp == InheritedType.inBothDiff) {
ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
elem.Reset(entry._value); // copy this entry
BaseAdd(elem,ThrowOnDuplicate,true); // Add it (so that is once existed in the temp
BaseRemove(entry.GetKey(this), false); // now remove it to for a remove instruction
}
}
}
}
foreach (Entry entry in sourceCollection.Items) {
if (entry._entryType != EntryType.Removed) {
InheritedType tp = (InheritedType)Inheritance[entry.GetKey(this)];
if (tp == InheritedType.inSelf || tp == InheritedType.inBothDiff ||
tp == InheritedType.inBothCopyNoRemove) {
ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
elem.Unmerge(entry._value, null, saveMode);
if (tp == InheritedType.inSelf) {
elem.RemoveAllInheritedLocks(); // If the key changed only local locks are kept
}
BaseAdd(elem,ThrowOnDuplicate,true); // Add it
}
}
}
}
else {
if (CollectionType == ConfigurationElementCollectionType.BasicMap ||
CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
foreach (Entry entry in sourceCollection.Items) {
bool FoundKeyInParent = false;
Entry parentEntrySaved = null;
if (entry._entryType == EntryType.Added ||
entry._entryType == EntryType.Replaced) {
bool InParent = false;
if (parentCollection != null) {
foreach (Entry parentEntry in parentCollection.Items) {
if (Object.Equals(entry.GetKey(this), parentEntry.GetKey(this))) {
// for basic map collection where the key is actually an element
// we do not want the merging behavior or data will not get written
// out for the properties if they match the first element deamed to be a parent
// For example <allow verbs="NewVerb" users="*"/> will loose the users because
// an entry exists in the root element.
if (!IsElementName(entry.GetKey(this).ToString())) {
// For elements which are not keyed by the element name
// need to be unmerged
FoundKeyInParent = true;
parentEntrySaved = parentEntry;
}
}
if (Object.Equals(entry._value, parentEntry._value)) {
FoundKeyInParent = true;
InParent = true; // in parent and the same exact values
parentEntrySaved = parentEntry;
break;
}
}
}
ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
if (!FoundKeyInParent) { // Unmerge is similar to a reset when used like this
// except that it handles the different update modes
// which Reset does not understand
elem.Unmerge(entry._value, null, saveMode); // copy this entry
BaseAdd(-1, elem,true); // Add it
}
else {
ConfigurationElement sourceItem = entry._value;
if (!InParent ||
(saveMode == ConfigurationSaveMode.Modified && sourceItem.IsModified()) ||
(saveMode == ConfigurationSaveMode.Full)) {
elem.Unmerge(entry._value, parentEntrySaved._value, saveMode);
BaseAdd(-1, elem,true); // Add it
}
}
}
}
}
}
}
}