1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using Internal.Runtime.CompilerServices;
10 namespace System.Runtime.InteropServices.WindowsRuntime
12 // This is a set of stub methods implementing the support for the IDictionary`2 interface on WinRT
13 // objects that support IMap`2. Used by the interop mashaling infrastructure.
15 // The methods on this class must be written VERY carefully to avoid introducing security holes.
16 // That's because they are invoked with special "this"! The "this" object
17 // for all of these methods are not MapToDictionaryAdapter objects. Rather, they are of type
18 // IMap<K, V>. No actual MapToDictionaryAdapter object is ever instantiated. Thus, you will see
19 // a lot of expressions that cast "this" to "IMap<K, V>".
20 internal sealed class MapToDictionaryAdapter
22 private MapToDictionaryAdapter()
24 Debug.Fail("This class is never instantiated");
27 // V this[K key] { get }
28 internal V Indexer_Get<K, V>(K key)
31 throw new ArgumentNullException(nameof(key));
34 IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
35 return Lookup(_this, key);
38 // V this[K key] { set }
39 internal void Indexer_Set<K, V>(K key, V value)
42 throw new ArgumentNullException(nameof(key));
45 IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
46 Insert(_this, key, value);
49 // ICollection<K> Keys { get }
50 internal ICollection<K> Keys<K, V>()
52 IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
53 IDictionary<K, V> dictionary = (IDictionary<K, V>)_this;
54 return new DictionaryKeyCollection<K, V>(dictionary);
57 // ICollection<V> Values { get }
58 internal ICollection<V> Values<K, V>()
60 IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
61 IDictionary<K, V> dictionary = (IDictionary<K, V>)_this;
62 return new DictionaryValueCollection<K, V>(dictionary);
65 // bool ContainsKey(K key)
66 internal bool ContainsKey<K, V>(K key)
69 throw new ArgumentNullException(nameof(key));
71 IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
72 return _this.HasKey(key);
75 // void Add(K key, V value)
76 internal void Add<K, V>(K key, V value)
79 throw new ArgumentNullException(nameof(key));
81 if (ContainsKey<K, V>(key))
82 throw new ArgumentException(SR.Argument_AddingDuplicate);
85 IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
86 Insert(_this, key, value);
89 // bool Remove(TKey key)
90 internal bool Remove<K, V>(K key)
93 throw new ArgumentNullException(nameof(key));
95 IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
96 if (!_this.HasKey(key))
106 if (HResults.E_BOUNDS == ex.HResult)
113 // bool TryGetValue(TKey key, out TValue value)
114 internal bool TryGetValue<K, V>(K key, out V value)
117 throw new ArgumentNullException(nameof(key));
119 IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
120 if (!_this.HasKey(key))
122 value = default!; // TODO-NULLABLE-GENERIC
128 value = Lookup(_this, key);
131 catch (KeyNotFoundException)
133 value = default!; // TODO-NULLABLE-GENERIC
140 private static V Lookup<K, V>(IMap<K, V> _this, K key)
142 Debug.Assert(null != key);
146 return _this.Lookup(key);
150 if (HResults.E_BOUNDS == ex.HResult)
151 throw new KeyNotFoundException(SR.Arg_KeyNotFound);
156 private static bool Insert<K, V>(IMap<K, V> _this, K key, V value)
158 Debug.Assert(null != key);
160 bool replaced = _this.Insert(key, value);