summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs')
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs323
1 files changed, 323 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs
new file mode 100644
index 0000000000..f26d50f953
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs
@@ -0,0 +1,323 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IReadOnlyDictionary`2 interface on WinRT
+ // objects that support IMapView`2. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not IMapViewToIReadOnlyDictionaryAdapter objects. Rather, they are of type
+ // IMapView<K, V>. No actual IMapViewToIReadOnlyDictionaryAdapter object is ever instantiated. Thus, you will see
+ // a lot of expressions that cast "this" to "IMapView<K, V>".
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class IMapViewToIReadOnlyDictionaryAdapter
+ {
+ private IMapViewToIReadOnlyDictionaryAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // V this[K key] { get }
+ [SecurityCritical]
+ internal V Indexer_Get<K, V>(K key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+ Contract.EndContractBlock();
+
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+ return Lookup(_this, key);
+ }
+
+ // IEnumerable<K> Keys { get }
+ [SecurityCritical]
+ internal IEnumerable<K> Keys<K, V>()
+ {
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+ IReadOnlyDictionary<K, V> roDictionary = (IReadOnlyDictionary<K, V>)_this;
+ return new ReadOnlyDictionaryKeyCollection<K, V>(roDictionary);
+ }
+
+ // IEnumerable<V> Values { get }
+ [SecurityCritical]
+ internal IEnumerable<V> Values<K, V>()
+ {
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+ IReadOnlyDictionary<K, V> roDictionary = (IReadOnlyDictionary<K, V>)_this;
+ return new ReadOnlyDictionaryValueCollection<K, V>(roDictionary);
+ }
+
+ // bool ContainsKey(K key)
+ [Pure]
+ [SecurityCritical]
+ internal bool ContainsKey<K, V>(K key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+ return _this.HasKey(key);
+ }
+
+ // bool TryGetValue(TKey key, out TValue value)
+ [SecurityCritical]
+ internal bool TryGetValue<K, V>(K key, out V value)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+
+ // It may be faster to call HasKey then Lookup. On failure, we would otherwise
+ // throw an exception from Lookup.
+ if (!_this.HasKey(key))
+ {
+ value = default(V);
+ return false;
+ }
+
+ try
+ {
+ value = _this.Lookup(key);
+ return true;
+ }
+ catch (Exception ex) // Still may hit this case due to a race condition
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ {
+ value = default(V);
+ return false;
+ }
+ throw;
+ }
+ }
+
+ #region Helpers
+
+ private static V Lookup<K, V>(IMapView<K, V> _this, K key)
+ {
+ Contract.Requires(null != key);
+
+ try
+ {
+ return _this.Lookup(key);
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new KeyNotFoundException(Environment.GetResourceString("Arg_KeyNotFound"));
+ throw;
+ }
+ }
+
+ #endregion Helpers
+ }
+
+ // Note: One day we may make these return IReadOnlyCollection<T>
+ [Serializable]
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class ReadOnlyDictionaryKeyCollection<TKey, TValue> : IEnumerable<TKey>
+ {
+ private readonly IReadOnlyDictionary<TKey, TValue> dictionary;
+
+ public ReadOnlyDictionaryKeyCollection(IReadOnlyDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ }
+
+ /*
+ public void CopyTo(TKey[] array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+ if (array.Length <= index && this.Count > 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException"));
+ if (array.Length - index < dictionary.Count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ int i = index;
+ foreach (KeyValuePair<TKey, TValue> mapping in dictionary)
+ {
+ array[i++] = mapping.Key;
+ }
+ }
+
+ public int Count {
+ get { return dictionary.Count; }
+ }
+
+ public bool Contains(TKey item)
+ {
+ return dictionary.ContainsKey(item);
+ }
+ */
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<TKey>)this).GetEnumerator();
+ }
+
+ public IEnumerator<TKey> GetEnumerator()
+ {
+ return new ReadOnlyDictionaryKeyEnumerator<TKey, TValue>(dictionary);
+ }
+ } // public class ReadOnlyDictionaryKeyCollection<TKey, TValue>
+
+
+ [Serializable]
+ internal sealed class ReadOnlyDictionaryKeyEnumerator<TKey, TValue> : IEnumerator<TKey>
+ {
+ private readonly IReadOnlyDictionary<TKey, TValue> dictionary;
+ private IEnumerator<KeyValuePair<TKey, TValue>> enumeration;
+
+ public ReadOnlyDictionaryKeyEnumerator(IReadOnlyDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ this.enumeration = dictionary.GetEnumerator();
+ }
+
+ void IDisposable.Dispose()
+ {
+ enumeration.Dispose();
+ }
+
+ public bool MoveNext()
+ {
+ return enumeration.MoveNext();
+ }
+
+ Object IEnumerator.Current {
+ get { return ((IEnumerator<TKey>)this).Current; }
+ }
+
+ public TKey Current {
+ get { return enumeration.Current.Key; }
+ }
+
+ public void Reset()
+ {
+ enumeration = dictionary.GetEnumerator();
+ }
+ } // class ReadOnlyDictionaryKeyEnumerator<TKey, TValue>
+
+
+ [Serializable]
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class ReadOnlyDictionaryValueCollection<TKey, TValue> : IEnumerable<TValue>
+ {
+ private readonly IReadOnlyDictionary<TKey, TValue> dictionary;
+
+ public ReadOnlyDictionaryValueCollection(IReadOnlyDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ }
+
+ /*
+ public void CopyTo(TValue[] array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+ if (array.Length <= index && this.Count > 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException"));
+ if (array.Length - index < dictionary.Count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ int i = index;
+ foreach (KeyValuePair<TKey, TValue> mapping in dictionary)
+ {
+ array[i++] = mapping.Value;
+ }
+ }
+
+ public int Count {
+ get { return dictionary.Count; }
+ }
+
+ public bool Contains(TValue item)
+ {
+ EqualityComparer<TValue> comparer = EqualityComparer<TValue>.Default;
+ foreach (TValue value in this)
+ if (comparer.Equals(item, value))
+ return true;
+ return false;
+ }
+ */
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<TValue>)this).GetEnumerator();
+ }
+
+ public IEnumerator<TValue> GetEnumerator()
+ {
+ return new ReadOnlyDictionaryValueEnumerator<TKey, TValue>(dictionary);
+ }
+ } // public class ReadOnlyDictionaryValueCollection<TKey, TValue>
+
+
+ [Serializable]
+ internal sealed class ReadOnlyDictionaryValueEnumerator<TKey, TValue> : IEnumerator<TValue>
+ {
+ private readonly IReadOnlyDictionary<TKey, TValue> dictionary;
+ private IEnumerator<KeyValuePair<TKey, TValue>> enumeration;
+
+ public ReadOnlyDictionaryValueEnumerator(IReadOnlyDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ this.enumeration = dictionary.GetEnumerator();
+ }
+
+ void IDisposable.Dispose()
+ {
+ enumeration.Dispose();
+ }
+
+ public bool MoveNext()
+ {
+ return enumeration.MoveNext();
+ }
+
+ Object IEnumerator.Current {
+ get { return ((IEnumerator<TValue>)this).Current; }
+ }
+
+ public TValue Current {
+ get { return enumeration.Current.Value; }
+ }
+
+ public void Reset()
+ {
+ enumeration = dictionary.GetEnumerator();
+ }
+ } // class ReadOnlyDictionaryValueEnumerator<TKey, TValue>
+
+}