diff --git a/src/Avalonia.Styling/Styling/Selectors.cs b/src/Avalonia.Styling/Styling/Selectors.cs
index 4284c7e798..deb677e04c 100644
--- a/src/Avalonia.Styling/Styling/Selectors.cs
+++ b/src/Avalonia.Styling/Styling/Selectors.cs
@@ -28,6 +28,9 @@ namespace Avalonia.Styling
/// The selector.
public static Selector Class(this Selector previous, string name)
{
+ Contract.Requires(name != null);
+ Contract.Requires(!string.IsNullOrWhiteSpace(name));
+
var tac = previous as TypeNameAndClassSelector;
if (tac != null)
@@ -59,6 +62,8 @@ namespace Avalonia.Styling
/// The selector.
public static Selector Is(this Selector previous, Type type)
{
+ Contract.Requires(type != null);
+
return TypeNameAndClassSelector.Is(previous, type);
}
@@ -81,6 +86,9 @@ namespace Avalonia.Styling
/// The selector.
public static Selector Name(this Selector previous, string name)
{
+ Contract.Requires(name != null);
+ Contract.Requires(!string.IsNullOrWhiteSpace(name));
+
var tac = previous as TypeNameAndClassSelector;
if (tac != null)
@@ -113,6 +121,8 @@ namespace Avalonia.Styling
/// The selector.
public static Selector OfType(this Selector previous, Type type)
{
+ Contract.Requires(type != null);
+
return TypeNameAndClassSelector.OfType(previous, type);
}
@@ -137,6 +147,8 @@ namespace Avalonia.Styling
/// The selector.
public static Selector PropertyEquals(this Selector previous, AvaloniaProperty property, object value)
{
+ Contract.Requires(property != null);
+
return new PropertyEqualsSelector(previous, property, value);
}
@@ -149,6 +161,8 @@ namespace Avalonia.Styling
/// The selector.
public static Selector PropertyEquals(this Selector previous, AvaloniaProperty property, object value)
{
+ Contract.Requires(property != null);
+
return new PropertyEqualsSelector(previous, property, value);
}
diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs
index 8d1216e1dc..8137ac3f48 100644
--- a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs
+++ b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs
@@ -50,10 +50,10 @@ namespace Avalonia.Markup.Parsers
{
case SelectorGrammar.OfTypeSyntax ofType:
- result = result.OfType(_typeResolver(ofType.Xmlns, ofType.TypeName));
+ result = result.OfType(Resolve(ofType.Xmlns, ofType.TypeName));
break;
case SelectorGrammar.IsSyntax @is:
- result = result.Is(_typeResolver(@is.Xmlns, @is.TypeName));
+ result = result.Is(Resolve(@is.Xmlns, @is.TypeName));
break;
case SelectorGrammar.ClassSyntax @class:
result = result.Class(@class.Class);
@@ -113,5 +113,18 @@ namespace Avalonia.Markup.Parsers
return result;
}
+
+ private Type Resolve(string xmlns, string typeName)
+ {
+ var result = _typeResolver(xmlns, typeName);
+
+ if (result == null)
+ {
+ var type = string.IsNullOrWhiteSpace(xmlns) ? typeName : xmlns + ':' + typeName;
+ throw new InvalidOperationException($"Could not resolve type '{type}'");
+ }
+
+ return result;
+ }
}
}
diff --git a/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs b/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs
index dba4573473..1b1a96a7e2 100644
--- a/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs
+++ b/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs
@@ -1,8 +1,6 @@
using System;
using Avalonia.Controls;
-using Avalonia.Controls.Primitives;
using Avalonia.Markup.Parsers;
-using Avalonia.Styling;
using Xunit;
namespace Avalonia.Markup.UnitTests.Parsers
@@ -15,5 +13,19 @@ namespace Avalonia.Markup.UnitTests.Parsers
var target = new SelectorParser((ns, type) => typeof(TextBlock));
var result = target.Parse("TextBlock[IsPointerOver=True]");
}
+
+ [Fact]
+ public void Throws_If_OfType_Type_Not_Found()
+ {
+ var target = new SelectorParser((ns, type) => null);
+ Assert.Throws(() => target.Parse("NotFound"));
+ }
+
+ [Fact]
+ public void Throws_If_Is_Type_Not_Found()
+ {
+ var target = new SelectorParser((ns, type) => null);
+ Assert.Throws(() => target.Parse(":is(NotFound)"));
+ }
}
}