[C] catch AmbiguousMatchException on GetProps (#3915)
authorStephane Delcroix <stephane@delcroix.org>
Fri, 28 Sep 2018 20:25:32 +0000 (22:25 +0200)
committerSamantha Houts <samhouts@users.noreply.github.com>
Fri, 28 Sep 2018 20:25:32 +0000 (13:25 -0700)
- fixes #3870

Xamarin.Forms.Core/Interactivity/PropertyCondition.cs
Xamarin.Forms.Core/Setter.cs
Xamarin.Forms.Core/StyleSheets/Style.cs
Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
Xamarin.Forms.Xaml/MarkupExtensionParser.cs

index 6a7dad8..a234975 100644 (file)
@@ -33,7 +33,14 @@ namespace Xamarin.Forms
                                //convert the value
                                if (_property != null && s_valueConverter != null)
                                {
-                                       Func<MemberInfo> minforetriever = () => Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
+                                       Func<MemberInfo> minforetriever = () =>
+                                       {
+                                               try {
+                                                       return Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
+                                               } catch (AmbiguousMatchException e) {
+                                                       throw new XamlParseException($"Multiple properties with name '{Property.DeclaringType}.{Property.PropertyName}' found.", new XmlLineInfo(), innerException: e);
+                                               }
+                                       };
                                        Value = s_valueConverter.Convert(Value, Property.ReturnType, minforetriever, null);
                                }
                        }
@@ -52,7 +59,14 @@ namespace Xamarin.Forms
                                //convert the value
                                if (_property != null && s_valueConverter != null)
                                {
-                                       Func<MemberInfo> minforetriever = () => Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
+                                       Func<MemberInfo> minforetriever = () =>
+                                       {
+                                               try {
+                                                       return Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
+                                               } catch (AmbiguousMatchException e) {
+                                                       throw new XamlParseException($"Multiple properties with name '{Property.DeclaringType}.{Property.PropertyName}' found.", new XmlLineInfo(), innerException: e);
+                                               }
+                                       };
                                        value = s_valueConverter.Convert(value, Property.ReturnType, minforetriever, null);
                                }
                                _triggerValue = value;
index c6cdc1b..224f09a 100644 (file)
@@ -22,15 +22,30 @@ namespace Xamarin.Forms
                {
                        if (Property == null)
                        {
-                               var lineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
-                               IXmlLineInfo lineInfo = lineInfoProvider != null ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+                               IXmlLineInfo lineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
                                throw new XamlParseException("Property not set", lineInfo);
                        }
                        var valueconverter = serviceProvider.GetService(typeof(IValueConverterProvider)) as IValueConverterProvider;
 
                        Func<MemberInfo> minforetriever =
                                () =>
-                               (MemberInfo)Property.DeclaringType.GetRuntimeProperty(Property.PropertyName) ?? (MemberInfo)Property.DeclaringType.GetRuntimeMethod("Get" + Property.PropertyName, new[] { typeof(BindableObject) });
+                               {
+                                       MemberInfo minfo = null;
+                                       try {
+                                               minfo = Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
+                                       } catch (AmbiguousMatchException e) {
+                                               IXmlLineInfo lineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+                                               throw new XamlParseException($"Multiple properties with name '{Property.DeclaringType}.{Property.PropertyName}' found.", lineInfo, innerException: e);
+                                       }
+                                       if (minfo != null)
+                                               return minfo;
+                                       try {
+                                               return Property.DeclaringType.GetRuntimeMethod("Get" + Property.PropertyName, new[] { typeof(BindableObject) });
+                                       } catch (AmbiguousMatchException e) {
+                                               IXmlLineInfo lineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+                                               throw new XamlParseException($"Multiple methods with name '{Property.DeclaringType}.Get{Property.PropertyName}' found.", lineInfo, innerException: e);
+                                       }
+                               };
 
                        object value = valueconverter.Convert(Value, Property.ReturnType, minforetriever, serviceProvider);
                        Value = value;
@@ -40,7 +55,7 @@ namespace Xamarin.Forms
                internal void Apply(BindableObject target, bool fromStyle = false)
                {
                        if (target == null)
-                               throw new ArgumentNullException("target");
+                               throw new ArgumentNullException(nameof(target));
                        if (Property == null)
                                return;
 
index 7cea0e5..6953321 100644 (file)
@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Runtime.CompilerServices;
+using System.Xml;
 using Xamarin.Forms.Xaml;
 
 namespace Xamarin.Forms.StyleSheets
@@ -84,9 +85,26 @@ namespace Xamarin.Forms.StyleSheets
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                static object Convert(object target, object value, BindableProperty property)
                {
-                       Func<MemberInfo> minforetriever = () =>    property.DeclaringType.GetRuntimeProperty(property.PropertyName) as MemberInfo
-                                                                                                       ?? property.DeclaringType.GetRuntimeMethod("Get" + property.PropertyName, new[] { typeof(BindableObject) }) as MemberInfo;
                        var serviceProvider = new StyleSheetServiceProvider(target, property);
+                       Func<MemberInfo> minforetriever =
+                               () =>
+                               {
+                                       MemberInfo minfo = null;
+                                       try {
+                                               minfo = property.DeclaringType.GetRuntimeProperty(property.PropertyName);
+                                       } catch (AmbiguousMatchException e) {
+                                               IXmlLineInfo lineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+                                               throw new XamlParseException($"Multiple properties with name '{property.DeclaringType}.{property.PropertyName}' found.", lineInfo, innerException: e);
+                                       }
+                                       if (minfo != null)
+                                               return minfo;
+                                       try {
+                                               return property.DeclaringType.GetRuntimeMethod("Get" + property.PropertyName, new[] { typeof(BindableObject) });
+                                       } catch (AmbiguousMatchException e) {
+                                               IXmlLineInfo lineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+                                               throw new XamlParseException($"Multiple methods with name '{property.DeclaringType}.Get{property.PropertyName}' found.", lineInfo, innerException: e);
+                                       }
+                               };
                        return value.ConvertTo(property.ReturnType, minforetriever, serviceProvider);
                }
 
index 6833254..46ccbc0 100644 (file)
@@ -473,9 +473,23 @@ namespace Xamarin.Forms.Xaml
 
                        Func<MemberInfo> minforetriever;
                        if (attached)
-                               minforetriever = () => property.DeclaringType.GetRuntimeMethod("Get" + property.PropertyName, new [] { typeof(BindableObject) });
+                               minforetriever = () =>
+                               {
+                                       try {
+                                               return property.DeclaringType.GetRuntimeMethod("Get" + property.PropertyName, new[] { typeof(BindableObject) });
+                                       } catch (AmbiguousMatchException e) {
+                                               throw new XamlParseException($"Multiple methods with name '{property.DeclaringType}.Get{property.PropertyName}' found.", lineInfo, innerException: e);
+                                       }
+                               };
                        else
-                               minforetriever = () => property.DeclaringType.GetRuntimeProperty(property.PropertyName);
+                               minforetriever = () =>
+                               {
+                                       try {
+                                               return property.DeclaringType.GetRuntimeProperty(property.PropertyName);
+                                       } catch (AmbiguousMatchException e) {
+                                               throw new XamlParseException($"Multiple properties with name '{property.DeclaringType}.{property.PropertyName}' found.", lineInfo, innerException: e);
+                                       }
+                               };
                        var convertedValue = value.ConvertTo(property.ReturnType, minforetriever, serviceProvider);
 
                        if (bindable != null) {
@@ -559,7 +573,11 @@ namespace Xamarin.Forms.Xaml
                        }
 #else
                        while (elementType != null && propertyInfo == null) {
-                               propertyInfo = elementType.GetProperty(localName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
+                               try {
+                                       propertyInfo = elementType.GetProperty(localName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
+                               } catch (AmbiguousMatchException e) {
+                                       throw new XamlParseException($"Multiple properties with name '{elementType}.{localName}' found.", lineInfo, innerException: e);
+                               }
                                elementType = elementType.BaseType;
                        }
 #endif
index 06185a8..f6421a2 100644 (file)
@@ -67,15 +67,32 @@ namespace Xamarin.Forms.Xaml
                                prop = ApplyPropertiesVisitor.GetContentPropertyName(t.GetTypeInfo());
                                if (prop == null)
                                        return;
-                               setter = t.GetRuntimeProperty(prop).SetMethod;
+                               try {
+                                       setter = t.GetRuntimeProperty(prop).SetMethod;
+                               } catch (AmbiguousMatchException e) {
+                                       var lineInfo = (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+                                       throw new XamlParseException($"Multiple properties with name  '{t}.{prop}' found.", lineInfo, innerException: e);
+                               }
                        }
-                       else
-                               setter = markupExtension.GetType().GetRuntimeProperty(prop).SetMethod;
+                       else {
+                               try
+                               {
+                                       setter = markupExtension.GetType().GetRuntimeProperty(prop).SetMethod;
+                               } catch (AmbiguousMatchException e) {
+                                       var lineInfo = (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+                                       throw new XamlParseException($"Multiple properties with name  '{markupExtension.GetType()}.{prop}' found.", lineInfo, innerException: e);
+                               }
 
+                       }
                        if (value == null && strValue != null)
                        {
-                               value = strValue.ConvertTo(markupExtension.GetType().GetRuntimeProperty(prop).PropertyType,
-                                       (Func<TypeConverter>)null, serviceProvider);
+                               try {
+                                       value = strValue.ConvertTo(markupExtension.GetType().GetRuntimeProperty(prop).PropertyType,
+                                               (Func<TypeConverter>)null, serviceProvider);
+                               } catch (AmbiguousMatchException e) {
+                                       var lineInfo = (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+                                       throw new XamlParseException($"Multiple properties with name  '{markupExtension.GetType()}.{prop}' found.", lineInfo, innerException: e);
+                               }
                        }
 
                        setter.Invoke(markupExtension, new[] { value });