summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Build.Tasks
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-09-23 09:01:22 +0200
committerJason Smith <jason.smith@xamarin.com>2016-09-23 00:01:22 -0700
commita5183bed8d38db411549733934b53380b93773b5 (patch)
tree51953e228a71cb59600c8c5ab001a959ee811a27 /Xamarin.Forms.Build.Tasks
parent1076e735697d393c7b10654f8dc7d9a91c7c13e1 (diff)
downloadxamarin-forms-a5183bed8d38db411549733934b53380b93773b5.tar.gz
xamarin-forms-a5183bed8d38db411549733934b53380b93773b5.tar.bz2
xamarin-forms-a5183bed8d38db411549733934b53380b93773b5.zip
[XamlC] Implement IValueProvider.PropertyType (#345)
Diffstat (limited to 'Xamarin.Forms.Build.Tasks')
-rw-r--r--Xamarin.Forms.Build.Tasks/BindablePropertyReferenceExtensions.cs61
-rw-r--r--Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs1
-rw-r--r--Xamarin.Forms.Build.Tasks/NodeILExtensions.cs131
-rw-r--r--Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs24
-rw-r--r--Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs87
-rw-r--r--Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj1
6 files changed, 137 insertions, 168 deletions
diff --git a/Xamarin.Forms.Build.Tasks/BindablePropertyReferenceExtensions.cs b/Xamarin.Forms.Build.Tasks/BindablePropertyReferenceExtensions.cs
new file mode 100644
index 00000000..159bbf5f
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/BindablePropertyReferenceExtensions.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml;
+
+using Mono.Cecil;
+
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class BindablePropertyReferenceExtensions
+ {
+ public static TypeReference GetBindablePropertyType(this FieldReference bpRef, IXmlLineInfo iXmlLineInfo, ModuleDefinition module)
+ {
+ if (!bpRef.Name.EndsWith("Property", StringComparison.InvariantCulture))
+ throw new XamlParseException($"The name of the bindable property {bpRef.Name} does not ends with \"Property\". This is the kind of convention the world is build upon, a bit like Planck's constant.", iXmlLineInfo);
+ var bpName = bpRef.Name.Substring(0, bpRef.Name.Length - 8);
+ var owner = bpRef.DeclaringType;
+ TypeReference _;
+
+ var getter = owner.GetProperty(pd => pd.Name == bpName, out _)?.GetMethod;
+ if (getter == null || getter.IsStatic || !getter.IsPublic)
+ getter = null;
+ getter = getter ?? owner.GetMethods(md => md.Name == $"Get{bpName}" &&
+ md.IsStatic &&
+ md.IsPublic &&
+ md.Parameters.Count == 1 &&
+ md.Parameters [0].ParameterType.FullName == "Xamarin.Forms.BindableObject", module).SingleOrDefault()?.Item1;
+
+ if (getter == null)
+ throw new XamlParseException($"Missing a public static Get{bpName} or a public instance property getter for the attached property \"{bpRef.DeclaringType}.{bpRef.Name}\"", iXmlLineInfo);
+ return getter.ReturnType;
+ }
+
+ public static TypeReference GetBindablePropertyTypeConverter(this FieldReference bpRef, ModuleDefinition module)
+ {
+ TypeReference _;
+ var owner = bpRef.DeclaringType;
+ var bpName = bpRef.Name.EndsWith("Property", StringComparison.Ordinal) ? bpRef.Name.Substring(0, bpRef.Name.Length - 8) : bpRef.Name;
+ var property = owner.GetProperty(pd => pd.Name == bpName, out _);
+ var staticGetter = owner.GetMethods(md => md.Name == $"Get{bpName}" &&
+ md.IsStatic &&
+ md.IsPublic &&
+ md.Parameters.Count == 1 &&
+ md.Parameters [0].ParameterType.FullName == "Xamarin.Forms.BindableObject", module).SingleOrDefault()?.Item1;
+
+ var attributes = new List<CustomAttribute>();
+ if (property != null && property.HasCustomAttributes)
+ attributes.AddRange(property.CustomAttributes);
+ if (property != null && property.PropertyType.Resolve().HasCustomAttributes)
+ attributes.AddRange(property.PropertyType.Resolve().CustomAttributes);
+ if (staticGetter != null && staticGetter.HasCustomAttributes)
+ attributes.AddRange(staticGetter.CustomAttributes);
+ if (staticGetter != null && staticGetter.ReturnType.Resolve().HasCustomAttributes)
+ attributes.AddRange(staticGetter.ReturnType.Resolve().CustomAttributes);
+
+ return attributes.FirstOrDefault(cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName))?.ConstructorArguments [0].Value as TypeReference;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs b/Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs
index 6240a201..3baa230c 100644
--- a/Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs
+++ b/Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs
@@ -1,6 +1,5 @@
using System;
using Mono.Cecil;
-using Mono.Cecil.Rocks;
namespace Xamarin.Forms.Build.Tasks
{
diff --git a/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs b/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
index 3902c71b..084151ba 100644
--- a/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
+++ b/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
@@ -37,10 +37,8 @@ namespace Xamarin.Forms.Build.Tasks
IEnumerable<Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes)
{
var module = context.Body.Method.Module;
- var targetTypeRef = GetBPReturnType(context, bpRef, node);
-
- TypeReference typeConverter;
- bpRef.HasTypeConverter(module, out typeConverter);
+ var targetTypeRef = bpRef.GetBindablePropertyType(node, module);
+ var typeConverter = bpRef.GetBindablePropertyTypeConverter(module);
return node.PushConvertedValue(context, targetTypeRef, typeConverter, pushServiceProvider, boxValueTypes,
unboxValueTypes);
@@ -186,101 +184,6 @@ namespace Xamarin.Forms.Build.Tasks
throw new XamlParseException(string.Format("Enum value not found for {0}", value), lineInfo);
}
- static bool HasTypeConverter(this FieldReference bpRef, ModuleDefinition module,
- out TypeReference typeConverterReference)
- {
- typeConverterReference = null;
-
- var declaringType = bpRef.DeclaringType;
- var bpName = bpRef.Name;
- var pName = bpName.EndsWith("Property", StringComparison.Ordinal) ? bpName.Substring(0, bpName.Length - 8) : bpName;
- var property = declaringType.Resolve().Properties.FirstOrDefault(p => p.Name == pName);
- CustomAttribute attr = null;
-
- if (property != null)
- {
- if (property.HasCustomAttributes)
- {
- attr =
- property.CustomAttributes.FirstOrDefault(
- cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
- }
- if (attr == null && property.PropertyType.Resolve().HasCustomAttributes)
- {
- attr =
- property.PropertyType.Resolve()
- .CustomAttributes.FirstOrDefault(
- cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
- }
-
- if (attr == null)
- return false;
-
- typeConverterReference = attr.ConstructorArguments[0].Value as TypeReference;
- return true;
- }
-
- var getters = bpRef.DeclaringType.GetMethods(md => md.Name == "Get" + pName &&
- md.IsStatic &&
- md.Parameters.Count() == 1 &&
- md.Parameters[0].ParameterType.FullName == "Xamarin.Forms.BindableObject", module).SingleOrDefault();
- if (getters != null)
- {
- if (getters.Item1.HasCustomAttributes)
- {
- attr =
- getters.Item1.CustomAttributes.FirstOrDefault(
- cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
- }
- else if (getters.Item1.ReturnType.Resolve().HasCustomAttributes)
- {
- attr =
- getters.Item1.ReturnType.Resolve()
- .CustomAttributes.FirstOrDefault(
- cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
- }
-
- if (attr == null)
- return false;
-
- typeConverterReference = attr.ConstructorArguments[0].Value as TypeReference;
- return true;
- }
-
- return false;
- }
-
- static TypeReference GetBPReturnType(ILContext context, FieldReference bpRef, IXmlLineInfo lineInfo)
- {
- //Find a property with a matching name
- var name = bpRef.Name;
- if (!name.EndsWith("Property", StringComparison.Ordinal))
- return context.Body.Method.Module.TypeSystem.Object;
- name = name.Substring(0, name.Length - 8);
-
- //First, check for a property
- TypeReference declaringTypeRef;
- var property = bpRef.DeclaringType.GetProperty(pd => pd.Name == name, out declaringTypeRef);
- if (property != null)
- return property.PropertyType;
-
- //Then check for getter or setter (attached BPs)
- var getters =
- bpRef.DeclaringType.GetMethods(md => md.Name == "Get" + name &&
- md.IsStatic &&
- md.Parameters.Count() == 1 &&
- md.Parameters [0].ParameterType.FullName == "Xamarin.Forms.BindableObject", context.Body.Method.Module)
- .SingleOrDefault();
- if (getters != null)
- return getters.Item1.ReturnType;
-
- //throws
- throw new XamlParseException(
- string.Format(
- "Can not find a Property named \"{0}\" or a static method named \"Get{0}\" for BindableProperty \"{1}\"", name,
- bpRef.Name), lineInfo);
- }
-
public static IEnumerable<Instruction> PushXmlLineInfo(this INode node, ILContext context)
{
var module = context.Body.Method.Module;
@@ -389,7 +292,30 @@ namespace Xamarin.Forms.Build.Tasks
}
}
- public static IEnumerable<Instruction> PushServiceProvider(this INode node, ILContext context)
+ static IEnumerable<Instruction> PushTargetProperty(FieldReference bpRef, PropertyReference propertyRef, TypeReference declaringTypeReference, ModuleDefinition module)
+ {
+ if (bpRef != null) {
+ yield return Instruction.Create(OpCodes.Ldsfld, bpRef);
+ yield break;
+ }
+ if (propertyRef != null) {
+// IL_0000: ldtoken [mscorlib]System.String
+// IL_0005: call class [mscorlib]System.Type class [mscorlib] System.Type::GetTypeFromHandle(valuetype [mscorlib] System.RuntimeTypeHandle)
+// IL_000a: ldstr "Foo"
+// IL_000f: callvirt instance class [mscorlib] System.Reflection.PropertyInfo class [mscorlib] System.Type::GetProperty(string)
+ var getTypeFromHandle = module.Import(typeof(Type).GetMethod("GetTypeFromHandle", new [] { typeof(RuntimeTypeHandle) }));
+ var getPropertyInfo = module.Import(typeof(Type).GetMethod("GetProperty", new [] { typeof(string) }));
+ yield return Instruction.Create(OpCodes.Ldtoken, module.Import(declaringTypeReference ?? propertyRef.DeclaringType));
+ yield return Instruction.Create(OpCodes.Call, module.Import(getTypeFromHandle));
+ yield return Instruction.Create(OpCodes.Ldstr, propertyRef.Name);
+ yield return Instruction.Create(OpCodes.Callvirt, module.Import(getPropertyInfo));
+ yield break;
+ }
+ yield return Instruction.Create(OpCodes.Ldnull);
+ yield break;
+ }
+
+ public static IEnumerable<Instruction> PushServiceProvider(this INode node, ILContext context, FieldReference bpRef = null, PropertyReference propertyRef = null, TypeReference declaringTypeReference = null)
{
var module = context.Body.Method.Module;
@@ -421,8 +347,11 @@ namespace Xamarin.Forms.Build.Tasks
foreach (var instruction in pushParentIl)
yield return instruction;
+ foreach (var instruction in PushTargetProperty(bpRef, propertyRef, declaringTypeReference, module))
+ yield return instruction;
+
var targetProviderCtor =
- module.Import(typeof (SimpleValueTargetProvider).GetConstructor(new[] { typeof (object[]) }));
+ module.Import(typeof (SimpleValueTargetProvider).GetConstructor(new[] { typeof (object[]), typeof(object) }));
yield return Instruction.Create(OpCodes.Newobj, targetProviderCtor);
yield return Instruction.Create(OpCodes.Callvirt, addService);
}
diff --git a/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs b/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs
index 472a5658..7a56c9d1 100644
--- a/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs
+++ b/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs
@@ -1,32 +1,14 @@
+using System;
using Mono.Cecil;
namespace Xamarin.Forms.Build.Tasks
{
static class PropertyDefinitionExtensions
{
- // public static PropertyDefinition MakeGeneric (this PropertyDefinition self, GenericInstanceType declaringTypeReference)
- // {
- // if (declaringTypeReference == null)
- // throw new ArgumentNullException ("declaringTypeReference");
- // if (self == null)
- // throw new ArgumentNullException ("self");
- //
- // var propertyType = declaringTypeReference.GenericArguments[((GenericParameter)self.PropertyType).Position];
- // self.PropertyType = propertyType;
- // self.SetMethod = self.SetMethod.MakeGeneric (propertyType).Resolve ();
- // self.GetMethod.ReturnType = propertyType;
- //
- // return self;
- // }
-
- public static TypeReference ResolveGenericPropertyType(this PropertyDefinition self,
- TypeReference declaringTypeReference)
+ public static TypeReference ResolveGenericPropertyType(this PropertyDefinition self, TypeReference declaringTypeReference)
{
if (self.PropertyType.IsGenericParameter)
- {
- return
- ((GenericInstanceType)declaringTypeReference).GenericArguments[((GenericParameter)self.PropertyType).Position];
- }
+ return ((GenericInstanceType)declaringTypeReference).GenericArguments [((GenericParameter)self.PropertyType).Position];
return self.PropertyType;
}
}
diff --git a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
index 9bc09ce9..734a34c2 100644
--- a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
@@ -81,10 +81,21 @@ namespace Xamarin.Forms.Build.Tasks
parentNode = parentNode.Parent;
}
+ if ((propertyName != XmlName.Empty || TryGetPropertyName(node, parentNode, out propertyName)) && skips.Contains(propertyName))
+ return;
+
//if this node is an IMarkupExtension, invoke ProvideValue() and replace the variable
var vardef = Context.Variables[node];
var vardefref = new VariableDefinitionReference(vardef);
- Context.IL.Append(ProvideValue(vardefref, Context, Module, node));
+ var localName = propertyName.LocalName;
+ TypeReference declaringTypeReference = null;
+ FieldReference bpRef = null;
+ PropertyDefinition propertyRef = null;
+ if (parentNode is IElementNode && propertyName != XmlName.Empty) {
+ bpRef = GetBindablePropertyReference(Context.Variables [(IElementNode)parentNode], propertyName.NamespaceURI, ref localName, Context, node);
+ propertyRef = Context.Variables [(IElementNode)parentNode].VariableType.GetProperty(pd => pd.Name == localName, out declaringTypeReference);
+ }
+ Context.IL.Append(ProvideValue(vardefref, Context, Module, node, bpRef:bpRef, propertyRef:propertyRef, propertyDeclaringTypeRef: declaringTypeReference));
if (vardef != vardefref.VariableDefinition)
{
vardef = vardefref.VariableDefinition;
@@ -92,11 +103,8 @@ namespace Xamarin.Forms.Build.Tasks
Context.Variables[node] = vardef;
}
- if (propertyName != XmlName.Empty || TryGetPropertyName(node, parentNode, out propertyName))
+ if (propertyName != XmlName.Empty)
{
- if (skips.Contains(propertyName))
- return;
-
if (propertyName == XmlName._CreateContent)
SetDataTemplate((IElementNode)parentNode, node, Context, node);
else
@@ -221,7 +229,7 @@ namespace Xamarin.Forms.Build.Tasks
}
public static IEnumerable<Instruction> ProvideValue(VariableDefinitionReference vardefref, ILContext context,
- ModuleDefinition module, ElementNode node)
+ ModuleDefinition module, ElementNode node, FieldReference bpRef = null, PropertyReference propertyRef = null, TypeReference propertyDeclaringTypeRef = null)
{
GenericInstanceType markupExtension;
IList<TypeReference> genericArguments;
@@ -242,7 +250,7 @@ namespace Xamarin.Forms.Build.Tasks
else
vardefref.VariableDefinition = new VariableDefinition(module.Import(genericArguments.First()));
yield return Instruction.Create(OpCodes.Ldloc, context.Variables[node]);
- foreach (var instruction in node.PushServiceProvider(context))
+ foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef))
yield return instruction;
yield return Instruction.Create(OpCodes.Callvirt, provideValue);
@@ -261,7 +269,7 @@ namespace Xamarin.Forms.Build.Tasks
vardefref.VariableDefinition = new VariableDefinition(module.Import(genericArguments.First()));
yield return Instruction.Create(OpCodes.Ldloc, context.Variables[node]);
- foreach (var instruction in node.PushServiceProvider(context))
+ foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef))
yield return instruction;
yield return Instruction.Create(OpCodes.Callvirt, provideValue);
yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition);
@@ -274,7 +282,7 @@ namespace Xamarin.Forms.Build.Tasks
vardefref.VariableDefinition = new VariableDefinition(module.TypeSystem.Object);
yield return Instruction.Create(OpCodes.Ldloc, context.Variables[node]);
- foreach (var instruction in node.PushServiceProvider(context))
+ foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef))
yield return instruction;
yield return Instruction.Create(OpCodes.Callvirt, provideValue);
yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition);
@@ -287,7 +295,7 @@ namespace Xamarin.Forms.Build.Tasks
vardefref.VariableDefinition = new VariableDefinition(module.TypeSystem.Object);
yield return Instruction.Create(OpCodes.Ldloc, context.Variables[node]);
- foreach (var instruction in node.PushServiceProvider(context))
+ foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef))
yield return instruction;
yield return Instruction.Create(OpCodes.Callvirt, provideValue);
yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition);
@@ -297,20 +305,8 @@ namespace Xamarin.Forms.Build.Tasks
public static IEnumerable<Instruction> SetPropertyValue(VariableDefinition parent, XmlName propertyName, INode valueNode, ILContext context, IXmlLineInfo iXmlLineInfo)
{
var module = context.Body.Method.Module;
-
var localName = propertyName.LocalName;
- TypeReference declaringTypeReference;
-
- //If it's an attached BP, update elementType and propertyName
- var bpOwnerType = parent.VariableType;
- GetNameAndTypeRef(ref bpOwnerType, propertyName.NamespaceURI, ref localName, context, iXmlLineInfo);
- FieldReference bpRef = bpOwnerType.GetField(fd => fd.Name == localName + "Property" &&
- fd.IsStatic &&
- fd.IsPublic, out declaringTypeReference);
- if (bpRef != null) {
- bpRef = module.Import(bpRef.ResolveGenericParameters(declaringTypeReference));
- bpRef.FieldType = module.Import(bpRef.FieldType);
- }
+ var bpRef = GetBindablePropertyReference(parent, propertyName.NamespaceURI, ref localName, context, iXmlLineInfo);
//If the target is an event, connect
if (CanConnectEvent(parent, localName))
@@ -339,6 +335,25 @@ namespace Xamarin.Forms.Build.Tasks
throw new XamlParseException($"No property, bindable property, or event found for '{localName}'", iXmlLineInfo);
}
+ static FieldReference GetBindablePropertyReference(VariableDefinition parent, string namespaceURI, ref string localName, ILContext context, IXmlLineInfo iXmlLineInfo)
+ {
+ var module = context.Body.Method.Module;
+ TypeReference declaringTypeReference;
+
+ //If it's an attached BP, update elementType and propertyName
+ var bpOwnerType = parent.VariableType;
+ GetNameAndTypeRef(ref bpOwnerType, namespaceURI, ref localName, context, iXmlLineInfo);
+ var name = $"{localName}Property";
+ FieldReference bpRef = bpOwnerType.GetField(fd => fd.Name == name &&
+ fd.IsStatic &&
+ fd.IsPublic, out declaringTypeReference);
+ if (bpRef != null) {
+ bpRef = module.Import(bpRef.ResolveGenericParameters(declaringTypeReference));
+ bpRef.FieldType = module.Import(bpRef.FieldType);
+ }
+ return bpRef;
+ }
+
static bool CanConnectEvent(VariableDefinition parent, string localName)
{
return parent.VariableType.GetEvent(ed => ed.Name == localName) != null;
@@ -448,28 +463,10 @@ namespace Xamarin.Forms.Build.Tasks
yield return Instruction.Create(OpCodes.Callvirt, module.Import(setBinding));
}
- static TypeReference GetBindablePropertyType(FieldReference bpRef, IXmlLineInfo iXmlLineInfo, ILContext context)
+ static bool CanSetValue(FieldReference bpRef, INode node, IXmlLineInfo iXmlLineInfo, ILContext context)
{
var module = context.Body.Method.Module;
- if (!bpRef.Name.EndsWith("Property", StringComparison.InvariantCulture))
- throw new XamlParseException($"The name of the bindable property {bpRef.Name} does not ends with \"Property\". This is the kind of convention the world is build upon, a bit like Planck's constant.", iXmlLineInfo);
- var bpName = bpRef.Name.Substring(0, bpRef.Name.Length - 8);
- var owner = bpRef.DeclaringType;
- TypeReference _;
-
- var getter = owner.GetProperty(pd => pd.Name == bpName, out _)?.GetMethod;
- if (getter == null || getter.IsStatic || !getter.IsPublic)
- getter = null;
- getter = getter ?? owner.GetMethods(md => md.Name == $"Get{bpName}" && md.IsStatic && md.IsPublic && md.Parameters.Count == 1, module).FirstOrDefault()?.Item1;
-
- if (getter == null)
- throw new XamlParseException($"Missing a public static Get{bpName} or a public instance property getter for the attached property \"{bpRef.DeclaringType}.{bpRef.Name}\"", iXmlLineInfo);
- return getter.ReturnType;
- }
-
- static bool CanSetValue(FieldReference bpRef, INode node, IXmlLineInfo iXmlLineInfo, ILContext context)
- {
if (bpRef == null)
return false;
@@ -484,7 +481,7 @@ namespace Xamarin.Forms.Build.Tasks
if (!context.Variables.TryGetValue(elementNode, out varValue))
return false;
- var bpTypeRef = GetBindablePropertyType(bpRef, iXmlLineInfo, context);
+ var bpTypeRef = bpRef.GetBindablePropertyType(iXmlLineInfo, module);
return varValue.VariableType.InheritsFromOrImplements(bpTypeRef);
}
@@ -504,7 +501,7 @@ namespace Xamarin.Forms.Build.Tasks
yield return Instruction.Create(OpCodes.Ldsfld, bpRef);
if (valueNode != null) {
- foreach (var instruction in valueNode.PushConvertedValue(context, bpRef, valueNode.PushServiceProvider(context), true, false))
+ foreach (var instruction in valueNode.PushConvertedValue(context, bpRef, valueNode.PushServiceProvider(context, bpRef:bpRef), true, false))
yield return instruction;
} else if (elementNode != null) {
yield return Instruction.Create(OpCodes.Ldloc, context.Variables [elementNode]);
@@ -572,7 +569,7 @@ namespace Xamarin.Forms.Build.Tasks
yield return Instruction.Create(OpCodes.Ldloc, parent);
if (valueNode != null) {
- foreach (var instruction in valueNode.PushConvertedValue(context, propertyType, new ICustomAttributeProvider [] { property, propertyType.Resolve() }, valueNode.PushServiceProvider(context), false, true))
+ foreach (var instruction in valueNode.PushConvertedValue(context, propertyType, new ICustomAttributeProvider [] { property, propertyType.Resolve() }, valueNode.PushServiceProvider(context, propertyRef:property), false, true))
yield return instruction;
yield return Instruction.Create(OpCodes.Callvirt, propertySetterRef);
} else if (elementNode != null) {
diff --git a/Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj b/Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj
index d81910bc..d24f42fc 100644
--- a/Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj
+++ b/Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj
@@ -90,6 +90,7 @@
<Compile Include="MethodDefinitionExtensions.cs" />
<Compile Include="CompiledMarkupExtensions\StaticExtension.cs" />
<Compile Include="CompiledMarkupExtensions\ICompiledMarkupExtension.cs" />
+ <Compile Include="BindablePropertyReferenceExtensions.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">