blob: 4f1465d31ec555fd80685d2becd2fdd1ccd7b65f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
using System;
using System.Reflection;
namespace Xamarin.Forms.Xaml
{
[ContentProperty("Key")]
public sealed class StaticResourceExtension : IMarkupExtension
{
public string Key { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (serviceProvider == null)
throw new ArgumentNullException("serviceProvider");
if (Key == null)
{
var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
var lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
throw new XamlParseException("you must specify a key in {StaticResource}", lineInfo);
}
var valueProvider = serviceProvider.GetService(typeof (IProvideValueTarget)) as IProvideParentValues;
if (valueProvider == null)
throw new ArgumentException();
var xmlLineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
var xmlLineInfo = xmlLineInfoProvider != null ? xmlLineInfoProvider.XmlLineInfo : null;
foreach (var p in valueProvider.ParentObjects)
{
var ve = p as VisualElement;
if (ve == null)
continue;
if (ve.Resources == null)
continue;
object res;
if (ve.Resources.TryGetValue(Key, out res))
{
return ConvertCompiledOnPlatform(res);
}
}
if (Application.Current != null && Application.Current.Resources != null &&
Application.Current.Resources.ContainsKey(Key))
{
var resource = Application.Current.Resources[Key];
return ConvertCompiledOnPlatform(resource);
}
throw new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo);
}
static object ConvertCompiledOnPlatform(object resource)
{
var actualType = resource.GetType();
if (actualType.GetTypeInfo().IsGenericType && actualType.GetGenericTypeDefinition() == typeof(OnPlatform<>))
{
// If we're accessing OnPlatform via a StaticResource in compiled XAML
// we'll have to handle the cast to the target type manually
// (Normally the compiled XAML handles this by calling `implicit` explicitly,
// but it doesn't know to do that when it's using a static resource)
var method = actualType.GetRuntimeMethod("op_Implicit", new[] { actualType });
resource = method.Invoke(resource, new[] { resource });
}
return resource;
}
}
}
|