3 using System.Reflection;
5 using Tizen.NUI.Binding;
6 using System.ComponentModel;
8 namespace Tizen.NUI.Xaml
10 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
11 [EditorBrowsable(EditorBrowsableState.Never)]
12 [ContentProperty("Key")]
13 public sealed class StaticResourceExtension : IMarkupExtension
15 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
16 [EditorBrowsable(EditorBrowsableState.Never)]
17 public string Key { get; set; }
19 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
20 [EditorBrowsable(EditorBrowsableState.Never)]
21 public object ProvideValue(IServiceProvider serviceProvider)
23 if (serviceProvider == null)
24 throw new ArgumentNullException(nameof(serviceProvider));
26 var lineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
27 var lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
28 throw new XamlParseException("you must specify a key in {StaticResource}", lineInfo);
30 var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideParentValues;
31 if (valueProvider == null)
32 throw new ArgumentException();
33 var xmlLineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
34 var xmlLineInfo = xmlLineInfoProvider != null ? xmlLineInfoProvider.XmlLineInfo : null;
35 object resource = null;
37 foreach (var p in valueProvider.ParentObjects) {
38 var irp = p as IResourcesProvider;
39 var resDict = irp != null && irp.IsResourcesCreated ? irp.XamlResources : p as ResourceDictionary;
42 if (resDict.TryGetValue(Key, out resource))
45 resource = resource ?? GetApplicationLevelResource(Key, xmlLineInfo);
47 var bp = valueProvider.TargetProperty as BindableProperty;
48 var pi = valueProvider.TargetProperty as PropertyInfo;
49 var propertyType = bp?.ReturnType ?? pi?.PropertyType;
50 if (propertyType == null) {
51 if (resource != null) {
52 if (resource.GetType().GetTypeInfo().IsGenericType && (resource.GetType().GetGenericTypeDefinition() == typeof(OnPlatform<>) || resource.GetType().GetGenericTypeDefinition() == typeof(OnIdiom<>))) {
53 // This is only there to support our backward compat story with pre 2.3.3 compiled Xaml project who was not providing TargetProperty
54 var method = resource.GetType().GetRuntimeMethod("op_Implicit", new[] { resource.GetType() });
56 resource = method.Invoke(null, new[] { resource });
62 if (propertyType.IsAssignableFrom(resource?.GetType()))
64 var implicit_op = resource?.GetType().GetImplicitConversionOperator(fromType: resource?.GetType(), toType: propertyType)
65 ?? propertyType.GetImplicitConversionOperator(fromType: resource?.GetType(), toType: propertyType);
66 if (implicit_op != null)
67 return implicit_op.Invoke(resource, new [] { resource });
69 if (resource != null) {
70 //Special case for https://bugzilla.xamarin.com/show_bug.cgi?id=59818
71 //On OnPlatform, check for an opImplicit from the targetType
72 if ( Device.Flags != null
73 && Device.Flags.Contains("xamlDoubleImplicitOpHack")
74 && resource.GetType().GetTypeInfo().IsGenericType
75 && (resource.GetType().GetGenericTypeDefinition() == typeof(OnPlatform<>))) {
76 var tType = resource.GetType().GenericTypeArguments[0];
77 var opImplicit = tType.GetImplicitConversionOperator(fromType: tType, toType: propertyType)
78 ?? propertyType.GetImplicitConversionOperator(fromType: tType, toType: propertyType);
80 if (opImplicit != null) {
81 //convert the OnPlatform<T> to T
82 var opPlatformImplicitConversionOperator = resource?.GetType().GetImplicitConversionOperator(fromType: resource?.GetType(), toType: tType);
83 resource = opPlatformImplicitConversionOperator?.Invoke(null, new[] { resource });
85 //and convert to toType
86 resource = opImplicit.Invoke(null, new[] { resource });
94 internal object GetApplicationLevelResource(string key, IXmlLineInfo xmlLineInfo)
96 object resource = null;
97 if (Application.Current == null || !((IResourcesProvider)Application.Current).IsResourcesCreated || !Application.Current.XamlResources.TryGetValue(Key, out resource))
98 throw new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo);