// This code is copy of the Apache 2 License code from the ASP.NET Core Repo. This is used to provide an easier experience for // developers by not throwing KeyNotFoundException exceptions. // https://github.com/aspnet/AspNetCore/blob/ab02951b37ac0cb09f8f6c3ed0280b46d89b06e0/src/Http/Http/src/Internal/ItemsDictionary.cs using System.Collections; using System.Collections.Generic; namespace Amazon.Lambda.AspNetCoreServer.Internal { internal class ItemsDictionary : IDictionary { private IDictionary _items; public ItemsDictionary() { } public ItemsDictionary(IDictionary items) { _items = items; } public IDictionary Items => this; // Replace the indexer with one that returns null for missing values object IDictionary.this[object key] { get { if (_items != null && _items.TryGetValue(key, out var value)) { return value; } return null; } set { EnsureDictionary(); _items[key] = value; } } void IDictionary.Add(object key, object value) { EnsureDictionary(); _items.Add(key, value); } bool IDictionary.ContainsKey(object key) => _items != null && _items.ContainsKey(key); ICollection IDictionary.Keys { get { if (_items == null) { return EmptyDictionary.Dictionary.Keys; } return _items.Keys; } } bool IDictionary.Remove(object key) => _items != null && _items.Remove(key); bool IDictionary.TryGetValue(object key, out object value) { value = null; return _items != null && _items.TryGetValue(key, out value); } ICollection IDictionary.Values { get { if (_items == null) { return EmptyDictionary.Dictionary.Values; } return _items.Values; } } void ICollection>.Add(KeyValuePair item) { EnsureDictionary(); _items.Add(item); } void ICollection>.Clear() => _items?.Clear(); bool ICollection>.Contains(KeyValuePair item) => _items != null && _items.Contains(item); void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { if (_items == null) { //Delegate to Empty Dictionary to do the argument checking. EmptyDictionary.Collection.CopyTo(array, arrayIndex); } _items.CopyTo(array, arrayIndex); } int ICollection>.Count => _items?.Count ?? 0; bool ICollection>.IsReadOnly => _items?.IsReadOnly ?? false; bool ICollection>.Remove(KeyValuePair item) { if (_items == null) { return false; } if (_items.TryGetValue(item.Key, out var value) && Equals(item.Value, value)) { return _items.Remove(item.Key); } return false; } private void EnsureDictionary() { if (_items == null) { _items = new Dictionary(); } } IEnumerator> IEnumerable>.GetEnumerator() => _items?.GetEnumerator() ?? EmptyEnumerator.Instance; IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator() ?? EmptyEnumerator.Instance; private class EmptyEnumerator : IEnumerator> { // In own class so only initalized if GetEnumerator is called on an empty ItemsDictionary public readonly static IEnumerator> Instance = new EmptyEnumerator(); public KeyValuePair Current => default; object IEnumerator.Current => null; public void Dispose() { } public bool MoveNext() => false; public void Reset() { } } private static class EmptyDictionary { // In own class so only initalized if CopyTo is called on an empty ItemsDictionary public readonly static IDictionary Dictionary = new Dictionary(); public static ICollection> Collection => Dictionary; } } }