From a5183bed8d38db411549733934b53380b93773b5 Mon Sep 17 00:00:00 2001 From: Stephane Delcroix Date: Fri, 23 Sep 2016 09:01:22 +0200 Subject: [XamlC] Implement IValueProvider.PropertyType (#345) --- .../MarkupExtensions/StaticResourceExtension.cs | 47 +++++++++------------- Xamarin.Forms.Xaml/XamlServiceProvider.cs | 22 +++++----- 2 files changed, 29 insertions(+), 40 deletions(-) (limited to 'Xamarin.Forms.Xaml') diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs index cf672a3d..a7f59be8 100644 --- a/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs +++ b/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs @@ -11,7 +11,7 @@ namespace Xamarin.Forms.Xaml public object ProvideValue(IServiceProvider serviceProvider) { if (serviceProvider == null) - throw new ArgumentNullException("serviceProvider"); + throw new ArgumentNullException(nameof(serviceProvider)); if (Key == null) { var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider; @@ -23,6 +23,7 @@ namespace Xamarin.Forms.Xaml throw new ArgumentException(); var xmlLineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider; var xmlLineInfo = xmlLineInfoProvider != null ? xmlLineInfoProvider.XmlLineInfo : null; + object resource = null; foreach (var p in valueProvider.ParentObjects) { @@ -30,35 +31,27 @@ namespace Xamarin.Forms.Xaml var resDict = ve?.Resources ?? p as ResourceDictionary; if (resDict == null) continue; - object res; - if (resDict.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); + if (resDict.TryGetValue(Key, out resource)) + break; } + if (resource == null && Application.Current != null && Application.Current.Resources != null && + Application.Current.Resources.ContainsKey(Key)) + resource = Application.Current.Resources [Key]; - throw new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo); - } + if (resource == null) + 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 }); - } + var bp = valueProvider.TargetProperty as BindableProperty; + var pi = valueProvider.TargetProperty as PropertyInfo; + var propertyType = bp?.ReturnType ?? pi?.PropertyType; + if (propertyType == null) + return resource; + if (propertyType.IsAssignableFrom(resource.GetType())) + return resource; + var implicit_op = resource.GetType().GetRuntimeMethod("op_Implicit", new [] { resource.GetType() }); + //This will invoke the op_implicit on OnPlatform<> + if (implicit_op != null && propertyType.IsAssignableFrom(implicit_op.ReturnType)) + return implicit_op.Invoke(resource, new [] { resource }); return resource; } diff --git a/Xamarin.Forms.Xaml/XamlServiceProvider.cs b/Xamarin.Forms.Xaml/XamlServiceProvider.cs index 77ed6345..5599cbbc 100644 --- a/Xamarin.Forms.Xaml/XamlServiceProvider.cs +++ b/Xamarin.Forms.Xaml/XamlServiceProvider.cs @@ -89,7 +89,7 @@ namespace Xamarin.Forms.Xaml.Internals } } - internal class XamlValueTargetProvider : IProvideParentValues, IProvideValueTarget + class XamlValueTargetProvider : IProvideParentValues, IProvideValueTarget { public XamlValueTargetProvider(object targetObject, INode node, HydratationContext context, object targetProperty) { @@ -102,14 +102,8 @@ namespace Xamarin.Forms.Xaml.Internals INode Node { get; } HydratationContext Context { get; } - public object TargetObject { get; } - - public object TargetProperty - { - get { throw new NotImplementedException(); } - private set { } - } + public object TargetProperty { get; } = null; IEnumerable IProvideParentValues.ParentObjects { @@ -141,15 +135,17 @@ namespace Xamarin.Forms.Xaml.Internals public class SimpleValueTargetProvider : IProvideParentValues, IProvideValueTarget { readonly object[] objectAndParents; + readonly object targetProperty; - public SimpleValueTargetProvider(object[] objectAndParents) + public SimpleValueTargetProvider(object[] objectAndParents, object targetProperty) { if (objectAndParents == null) - throw new ArgumentNullException("objectAndParents"); + throw new ArgumentNullException(nameof(objectAndParents)); if (objectAndParents.Length == 0) throw new ArgumentException(); this.objectAndParents = objectAndParents; + this.targetProperty = targetProperty; } IEnumerable IProvideParentValues.ParentObjects @@ -164,7 +160,7 @@ namespace Xamarin.Forms.Xaml.Internals object IProvideValueTarget.TargetProperty { - get { throw new NotImplementedException(); } + get { return targetProperty; } } } @@ -249,7 +245,7 @@ namespace Xamarin.Forms.Xaml.Internals XmlType xmlType, IXmlLineInfo xmlInfo, Assembly currentAssembly, out XamlParseException exception); } - internal class XamlRootObjectProvider : IRootObjectProvider + class XamlRootObjectProvider : IRootObjectProvider { public XamlRootObjectProvider(object rootObject) { @@ -269,7 +265,7 @@ namespace Xamarin.Forms.Xaml.Internals public IXmlLineInfo XmlLineInfo { get; } } - internal interface INameScopeProvider + interface INameScopeProvider { INameScope NameScope { get; } } -- cgit v1.2.3