// TODO:srcM.Changing can fail after our Changing is done. // For example, if another subsciber is called after this and it cancels the update. // Then the target will have the entry, this one - doesn't. private void MetadataChanging(object sender, VariableMetadataChangingEventArgs e) { if (IsReadOnlyEntry(e.Key)) { e.Cancel = true; return; } if (!IsHiddenEntry(e.Key)) { if (proposedMetadataEntries.Exists(entry => entry.Key == e.Key && AreEquals(entry.Value, e.ProposedValue))) { return; } var pair = new KeyValuePair <string, object>(e.Key, e.ProposedValue); try { proposedMetadataEntries.Add(pair); target.Metadata[e.Key] = e.ProposedValue; } finally { proposedMetadataEntries.Remove(pair); } } }
/// <summary> /// Gets the metadata value or sets new value for the given key. /// </summary> /// <param name="key">The name of the metadata attribute to get.</param> /// <returns>Value corresponding to the given key.</returns> /// <remarks> /// <para> /// The indexer returns committed values. /// See remarks for <see cref="this[string, SchemaVersion]"/>. /// </para> /// </remarks> /// <seealso cref="this[string, SchemaVersion]"/> /// <seealso cref="SchemaVersion"/> /// <seealso cref="Variable"/> public virtual object this[string key] { get { return(this[key, SchemaVersion.Committed]); } set { if (readOnly) { throw new Exception("MetadataDictionary is read only"); } CheckKey(key); CheckValue(value); // Constraints on name if (key == KeyForName) { if (value != null && !(value is string)) { throw new Exception("Name of a variable must be a string"); } } object old = null; object cloneValue = null; if (value is ICloneable) { cloneValue = ((ICloneable)value).Clone(); } else { cloneValue = value; } bool changed = true; if (HasChanges) { if (modified.ContainsKey(key)) { old = modified[key]; changed = !AreEquals(old, cloneValue); } else if (dictionary.ContainsKey(key)) { old = dictionary[key]; changed = !AreEquals(old, cloneValue); } } else if (dictionary.ContainsKey(key)) { changed = !AreEquals(old = dictionary[key], cloneValue); } if (!changed) { return; } VariableMetadataChangingEventArgs e = new VariableMetadataChangingEventArgs( key, cloneValue, old); if (Changing != null) { Changing(this, e); if (e.Cancel) { throw new Exception("Metadata changing is cancelled."); } } if (modified == null) { modified = new Dictionary <string, object>(); } modified[key] = e.ProposedValue; if (Changed != null) { Changed(this, new VariableMetadataChangedEventArgs(key, e.ProposedValue)); } } }