[Test]
public void UnknownGenericType()
{
+ XamlLoader.FallbackTypeResolver = (p, type) => type ??
+ (p.Any(i => i.TypeName == "MyCustomButton`1") ? typeof(ProxyGenericButton<>) : typeof(MockView));
+
+ var xaml = @"
+ <ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:local=""clr-namespace:MissingNamespace;assembly=MissingAssembly""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml"">
+ <local:MyCustomButton x:TypeArguments=""local:MyCustomType"" />
+ </ContentPage>";
+
+ var page = (ContentPage)XamlLoader.Create(xaml, true);
+ Assert.That(page.Content, Is.TypeOf<ProxyGenericButton<MockView>>());
+ }
+
+ [Test]
+ public void InvalidGenericType()
+ {
+ int exceptionCount = 0;
+#pragma warning disable 0618 // Type or member is obsolete
+ Forms.Internals.ResourceLoader.ExceptionHandler = _ => exceptionCount++;
XamlLoader.FallbackTypeResolver = (p, type) => type ?? typeof(MockView);
+#pragma warning restore 0618 // Type or member is obsolete
var xaml = @"
<ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
</ContentPage>";
var page = (ContentPage)XamlLoader.Create(xaml, true);
- Assert.That(page.Content, Is.TypeOf<MockView>());
+ Assert.That(page.Content, Is.Null);
+ Assert.That(exceptionCount, Is.EqualTo(1));
}
[Test]
XamlLoader.FallbackTypeResolver = (p, type) =>
{
+ if (type != null)
+ return type;
Assert.That(p.Select(i => i.TypeName), Has.Some.EqualTo("GenericContentPage`1"));
- return typeof(ContentPage);
+ return typeof(ProxyGenericContentPage<>);
};
Assert.DoesNotThrow(() => XamlLoader.Create(xaml, true));
}
}
+ public class ProxyGenericContentPage<T> : ContentPage { }
+
+ public class ProxyGenericButton<T> : Button { }
+
public class InstantiateThrows
{
public InstantiateThrows() => throw new InvalidOperationException();
var typeArguments = xmlType.TypeArguments;
exception = null;
+#if NETSTANDARD2_0
+ if (type == null)
+ {
+ // This covers the scenario where the AppDomain's loaded
+ // assemblies might have changed since this method was first
+ // called. This occurred during unit test runs and could
+ // conceivably occur in the field.
+ if (!hasRetriedNsSearch) {
+ hasRetriedNsSearch = true;
+ s_xmlnsDefinitions = null;
+ goto retry;
+ }
+ }
+#endif
+
+ if (XamlLoader.FallbackTypeResolver != null)
+ type = XamlLoader.FallbackTypeResolver(potentialTypes, type);
+
if (type != null && typeArguments != null)
{
XamlParseException innerexception = null;
exception = innerexception;
return null;
}
- type = type.MakeGenericType(args);
- }
-#if NETSTANDARD2_0
- if (type == null)
- {
- // This covers the scenario where the AppDomain's loaded
- // assemblies might have changed since this method was first
- // called. This occurred during unit test runs and could
- // conceivably occur in the field.
- if (!hasRetriedNsSearch) {
- hasRetriedNsSearch = true;
- s_xmlnsDefinitions = null;
- goto retry;
+ try {
+ type = type.MakeGenericType(args);
+ } catch (InvalidOperationException) {
+ exception = new XamlParseException($"Type {type} is not a GenericTypeDefinition", xmlInfo);
}
}
-#endif
-
- if (XamlLoader.FallbackTypeResolver != null)
- type = XamlLoader.FallbackTypeResolver(potentialTypes, type);
if (type == null)
exception = new XamlParseException($"Type {xmlType.Name} not found in xmlns {xmlType.NamespaceUri}", xmlInfo);