| File: Collections\ReadOnlyConvertingDictionary.cs | Web Access |
| Project: src\msbuild\src\Build\Microsoft.Build.csproj (Microsoft.Build) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using Microsoft.Build.Shared; #nullable disable namespace Microsoft.Build.Collections { /// <summary> /// Implementation of a dictionary which acts as a read-only wrapper on another dictionary, but /// converts values as they are accessed to another type. /// </summary> /// <typeparam name="K">The backing dictionary's key type.</typeparam> /// <typeparam name="V">The backing dictionary's value type.</typeparam> /// <typeparam name="N">The desired value type.</typeparam> internal class ReadOnlyConvertingDictionary<K, V, N> : IDictionary<K, N> { /// <summary> /// The backing dictionary. /// </summary> private readonly IDictionary<K, V> _backing; /// <summary> /// The delegate used to convert values. /// </summary> private readonly Func<V, N> _converter; /// <summary> /// Constructor. /// </summary> internal ReadOnlyConvertingDictionary(IDictionary<K, V> backing, Func<V, N> converter) { ArgumentNullException.ThrowIfNull(backing); ArgumentNullException.ThrowIfNull(converter); _backing = backing; _converter = converter; } #region IDictionary<string,string> Members /// <summary> /// Returns the collection of keys in the dictionary. /// </summary> public ICollection<K> Keys => _backing.Keys; /// <summary> /// Returns the collection of values in the dictionary. /// </summary> public ICollection<N> Values => InternalError.Throw<ICollection<N>>("Values is not supported on ReadOnlyConvertingDictionary."); /// <summary> /// Returns the number of items in the collection. /// </summary> public int Count => _backing.Count; /// <summary> /// Returns true if the collection is read-only. /// </summary> public bool IsReadOnly => true; /// <summary> /// Accesses the value for the specified key. /// </summary> public N this[K key] { get => _converter(_backing[key]); set => ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection"); } /// <summary> /// Adds a value to the dictionary. /// </summary> public void Add(K key, N value) { ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection"); } /// <summary> /// Returns true if the dictionary contains the specified key. /// </summary> public bool ContainsKey(K key) { return _backing.ContainsKey(key); } /// <summary> /// Removes the entry for the specified key from the dictionary. /// </summary> public bool Remove(K key) { ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection"); return false; } /// <summary> /// Attempts to find the value for the specified key in the dictionary. /// </summary> public bool TryGetValue(K key, out N value) { if (_backing.TryGetValue(key, out V originalValue)) { value = _converter(originalValue); return true; } value = default(N); return false; } #endregion #region ICollection<KeyValuePair<string,string>> Members /// <summary> /// Adds an item to the collection. /// </summary> public void Add(KeyValuePair<K, N> item) { ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection"); } /// <summary> /// Clears the collection. /// </summary> public void Clear() { ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection"); } /// <summary> /// Returns true ff the collection contains the specified item. /// </summary> public bool Contains(KeyValuePair<K, N> item) { ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedConvertingCollectionValueToBacking"); return false; } /// <summary> /// Copies all of the elements of the collection to the specified array. /// </summary> public void CopyTo(KeyValuePair<K, N>[] array, int arrayIndex) { Assumed.GreaterThanOrEqual(array.Length - arrayIndex, _backing.Count, "Specified array size insufficient to hold the contents of the collection."); foreach (KeyValuePair<K, V> pair in _backing) { array[arrayIndex++] = KeyValueConverter(pair); } } /// <summary> /// Remove an item from the dictionary. /// </summary> public bool Remove(KeyValuePair<K, N> item) { ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection"); return false; } #endregion #region IEnumerable<KeyValuePair<K, N>> Members /// <summary> /// Implementation of generic IEnumerable.GetEnumerator() /// </summary> public IEnumerator<KeyValuePair<K, N>> GetEnumerator() { return new ConvertingEnumerable<KeyValuePair<K, V>, KeyValuePair<K, N>>(_backing, KeyValueConverter).GetEnumerator(); } #endregion #region IEnumerable Members /// <summary> /// Implementation of IEnumerable.GetEnumerator() /// </summary> System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((IEnumerable<KeyValuePair<K, N>>)this).GetEnumerator(); } #endregion /// <summary> /// Delegate used by ConvertingEnumerable /// </summary> private KeyValuePair<K, N> KeyValueConverter(KeyValuePair<K, V> original) { return new KeyValuePair<K, N>(original.Key, _converter(original.Value)); } } }