using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Linq; using System.Reflection; using Xamarin.Forms.Internals; namespace Xamarin.Forms { public class ResourceDictionary : IResourceDictionary, IDictionary { static ConditionalWeakTable s_instances = new ConditionalWeakTable(); readonly Dictionary _innerDictionary = new Dictionary(); Type _mergedWith; [TypeConverter (typeof(TypeTypeConverter))] public Type MergedWith { get { return _mergedWith; } set { if (_mergedWith == value) return; if (!typeof(ResourceDictionary).GetTypeInfo().IsAssignableFrom(value.GetTypeInfo())) throw new ArgumentException("MergedWith should inherit from ResourceDictionary"); _mergedWith = value; if (_mergedWith == null) return; _mergedInstance = s_instances.GetValue(_mergedWith,(key) => (ResourceDictionary)Activator.CreateInstance(key)); OnValuesChanged (_mergedInstance.ToArray()); } } ResourceDictionary _mergedInstance; void ICollection>.Add(KeyValuePair item) { ((ICollection>)_innerDictionary).Add(item); OnValuesChanged(item); } public void Clear() { _innerDictionary.Clear(); } bool ICollection>.Contains(KeyValuePair item) { return ((ICollection>)_innerDictionary).Contains(item) || (_mergedInstance != null && _mergedInstance.Contains(item)); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { ((ICollection>)_innerDictionary).CopyTo(array, arrayIndex); } public int Count { get { return _innerDictionary.Count; } } bool ICollection>.IsReadOnly { get { return ((ICollection>)_innerDictionary).IsReadOnly; } } bool ICollection>.Remove(KeyValuePair item) { return ((ICollection>)_innerDictionary).Remove(item); } public void Add(string key, object value) { if (ContainsKey(key)) throw new ArgumentException($"A resource with the key '{key}' is already present in the ResourceDictionary."); _innerDictionary.Add(key, value); OnValueChanged(key, value); } public bool ContainsKey(string key) { return _innerDictionary.ContainsKey(key); } [IndexerName("Item")] public object this[string index] { get { if (_innerDictionary.ContainsKey(index)) return _innerDictionary[index]; if (_mergedInstance != null && _mergedInstance.ContainsKey(index)) return _mergedInstance[index]; throw new KeyNotFoundException($"The resource '{index}' is not present in the dictionary."); } set { _innerDictionary[index] = value; OnValueChanged(index, value); } } public ICollection Keys { get { return _innerDictionary.Keys; } } public bool Remove(string key) { return _innerDictionary.Remove(key); } public ICollection Values { get { return _innerDictionary.Values; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerator> GetEnumerator() { return _innerDictionary.GetEnumerator(); } internal IEnumerable> MergedResources { get { if (_mergedInstance != null) foreach (var r in _mergedInstance.MergedResources) yield return r; foreach (var r in _innerDictionary) yield return r; } } public bool TryGetValue(string key, out object value) { return _innerDictionary.TryGetValue(key, out value) || (_mergedInstance != null && _mergedInstance.TryGetValue(key, out value)); } event EventHandler IResourceDictionary.ValuesChanged { add { ValuesChanged += value; } remove { ValuesChanged -= value; } } public void Add(Style style) { if (string.IsNullOrEmpty(style.Class)) Add(style.TargetType.FullName, style); else { IList