maui-linux/Xamarin.Forms.Core/ResourceDictionary.cs

178 строки
4.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Linq;
namespace Xamarin.Forms
{
public class ResourceDictionary : IResourceDictionary, IDictionary<string, object>
{
readonly Dictionary<string, object> _innerDictionary = new Dictionary<string, object>();
Type _mergedWith;
[TypeConverter (typeof(TypeTypeConverter))]
public Type MergedWith {
get { return _mergedWith; }
set {
if (_mergedWith == value)
return;
_mergedWith = value;
if (_mergedWith == null)
return;
_mergedInstance = _mergedWith.GetTypeInfo().BaseType.GetTypeInfo().DeclaredMethods.First(mi => mi.Name == "GetInstance").Invoke(null, new object[] {_mergedWith}) as ResourceDictionary;
OnValuesChanged (_mergedInstance.ToArray());
}
}
static Dictionary<Type, ResourceDictionary> _instances;
static ResourceDictionary GetInstance(Type type)
{
_instances = _instances ?? new Dictionary<Type, ResourceDictionary>();
ResourceDictionary rd;
if (!_instances.TryGetValue(type, out rd))
{
rd = ((ResourceDictionary)Activator.CreateInstance(type));
_instances [type] = rd;
}
return rd;
}
ResourceDictionary _mergedInstance;
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item)
{
((ICollection<KeyValuePair<string, object>>)_innerDictionary).Add(item);
OnValuesChanged(item);
}
public void Clear()
{
_innerDictionary.Clear();
}
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
{
return ((ICollection<KeyValuePair<string, object>>)_innerDictionary).Contains(item);
}
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<string, object>>)_innerDictionary).CopyTo(array, arrayIndex);
}
public int Count
{
get { return _innerDictionary.Count + (_mergedInstance != null ? _mergedInstance.Count: 0); }
}
bool ICollection<KeyValuePair<string, object>>.IsReadOnly
{
get { return ((ICollection<KeyValuePair<string, object>>)_innerDictionary).IsReadOnly; }
}
bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item)
{
return ((ICollection<KeyValuePair<string, object>>)_innerDictionary).Remove(item);
}
public void Add(string key, object value)
{
_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<string> Keys
{
get { return _innerDictionary.Keys; }
}
public bool Remove(string key)
{
return _innerDictionary.Remove(key);
}
public ICollection<object> Values
{
get { return _innerDictionary.Values; }
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
var rd = (IEnumerable<KeyValuePair<string,object>>)_innerDictionary;
if (_mergedInstance != null)
rd = rd.Concat(_mergedInstance._innerDictionary);
return rd.GetEnumerator();
}
public bool TryGetValue(string key, out object value)
{
return _innerDictionary.TryGetValue(key, out value) || (_mergedInstance != null && _mergedInstance.TryGetValue(key, out value));
}
event EventHandler<ResourcesChangedEventArgs> 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<Style> classes;
object outclasses;
if (!TryGetValue(Style.StyleClassPrefix + style.Class, out outclasses) || (classes = outclasses as IList<Style>) == null)
classes = new List<Style>();
classes.Add(style);
this[Style.StyleClassPrefix + style.Class] = classes;
}
}
void OnValueChanged(string key, object value)
{
OnValuesChanged(new KeyValuePair<string, object>(key, value));
}
void OnValuesChanged(params KeyValuePair<string, object>[] values)
{
if (values == null || values.Length == 0)
return;
ValuesChanged?.Invoke(this, new ResourcesChangedEventArgs(values));
}
event EventHandler<ResourcesChangedEventArgs> ValuesChanged;
}
}