summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-12-06 07:56:08 (GMT)
committerGitHub <noreply@github.com>2016-12-06 07:56:08 (GMT)
commitff1bf0b5ef5ceb9b5b4b65809f91c4c608d26fff (patch)
tree3188b6fd66414745563c1d99af56dd4e6cdd0c79 /Xamarin.Forms.Core
parentc612398bd26bdb0e0d92c7edf5bb102657868431 (diff)
downloadxamarin-forms-ff1bf0b5ef5ceb9b5b4b65809f91c4c608d26fff.zip
xamarin-forms-ff1bf0b5ef5ceb9b5b4b65809f91c4c608d26fff.tar.gz
xamarin-forms-ff1bf0b5ef5ceb9b5b4b65809f91c4c608d26fff.tar.bz2
ResourceDictionary fixes (#536)
* [C] avoid leaking RDs, remove reflection call, validate arguments * [C,Xaml] The only way to get merged values are internal
Diffstat (limited to 'Xamarin.Forms.Core')
-rw-r--r--Xamarin.Forms.Core/ResourceDictionary.cs46
-rw-r--r--Xamarin.Forms.Core/ResourcesExtensions.cs8
2 files changed, 28 insertions, 26 deletions
diff --git a/Xamarin.Forms.Core/ResourceDictionary.cs b/Xamarin.Forms.Core/ResourceDictionary.cs
index 0747eaa..ed3ea7f 100644
--- a/Xamarin.Forms.Core/ResourceDictionary.cs
+++ b/Xamarin.Forms.Core/ResourceDictionary.cs
@@ -2,13 +2,14 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
-using System.Reflection;
using System.Linq;
+using System.Reflection;
namespace Xamarin.Forms
{
public class ResourceDictionary : IResourceDictionary, IDictionary<string, object>
{
+ static ConditionalWeakTable<Type, ResourceDictionary> s_instances = new ConditionalWeakTable<Type, ResourceDictionary>();
readonly Dictionary<string, object> _innerDictionary = new Dictionary<string, object>();
Type _mergedWith;
@@ -18,28 +19,19 @@ namespace Xamarin.Forms
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 = _mergedWith.GetTypeInfo().BaseType.GetTypeInfo().DeclaredMethods.First(mi => mi.Name == "GetInstance").Invoke(null, new object[] {_mergedWith}) as ResourceDictionary;
+ _mergedInstance = s_instances.GetValue(_mergedWith,(key) => (ResourceDictionary)Activator.CreateInstance(key));
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)
@@ -65,7 +57,7 @@ namespace Xamarin.Forms
public int Count
{
- get { return _innerDictionary.Count + (_mergedInstance != null ? _mergedInstance.Count: 0); }
+ get { return _innerDictionary.Count; }
}
bool ICollection<KeyValuePair<string, object>>.IsReadOnly
@@ -96,8 +88,6 @@ namespace Xamarin.Forms
{
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
@@ -129,14 +119,26 @@ namespace Xamarin.Forms
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
- var rd = (IEnumerable<KeyValuePair<string,object>>)_innerDictionary;
- if (_mergedInstance != null)
- rd = rd.Concat(_mergedInstance._innerDictionary);
- return rd.GetEnumerator();
+ return _innerDictionary.GetEnumerator();
+ }
+
+ internal IEnumerable<KeyValuePair<string, object>> 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);
+ }
+
+ internal bool TryGetMergedValue(string key, out object value)
+ {
return _innerDictionary.TryGetValue(key, out value) || (_mergedInstance != null && _mergedInstance.TryGetValue(key, out value));
}
diff --git a/Xamarin.Forms.Core/ResourcesExtensions.cs b/Xamarin.Forms.Core/ResourcesExtensions.cs
index a75e264..8930abf 100644
--- a/Xamarin.Forms.Core/ResourcesExtensions.cs
+++ b/Xamarin.Forms.Core/ResourcesExtensions.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Xamarin.Forms
{
- internal static class ResourcesExtensions
+ static class ResourcesExtensions
{
public static IEnumerable<KeyValuePair<string, object>> GetMergedResources(this IElement element)
{
@@ -11,10 +11,10 @@ namespace Xamarin.Forms
while (element != null)
{
var ve = element as IResourcesProvider;
- if (ve != null && ve.Resources != null && ve.Resources.Count != 0)
+ if (ve != null && ve.Resources != null)
{
- resources = resources ?? new Dictionary<string, object>(ve.Resources.Count);
- foreach (KeyValuePair<string, object> res in ve.Resources)
+ resources = resources ?? new Dictionary<string, object>();
+ foreach (KeyValuePair<string, object> res in ve.Resources.MergedResources)
if (!resources.ContainsKey(res.Key))
resources.Add(res.Key, res.Value);
else if (res.Key.StartsWith(Style.StyleClassPrefix, StringComparison.Ordinal))