[X] internal CreateFromXaml () (#77)
This commit is contained in:
Родитель
f975a6f2e3
Коммит
c92297047c
|
@ -5,7 +5,7 @@ namespace Xamarin.Forms.Build.Tasks
|
||||||
{
|
{
|
||||||
class ILRootNode : RootNode
|
class ILRootNode : RootNode
|
||||||
{
|
{
|
||||||
public ILRootNode(XmlType xmlType, TypeReference typeReference) : base(xmlType)
|
public ILRootNode(XmlType xmlType, TypeReference typeReference) : base(xmlType, null)
|
||||||
{
|
{
|
||||||
TypeReference = typeReference;
|
TypeReference = typeReference;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
||||||
var bindable = new Bindable ();
|
var bindable = new Bindable ();
|
||||||
|
|
||||||
Assert.IsNull (bindable.Baz);
|
Assert.IsNull (bindable.Baz);
|
||||||
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
|
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
|
||||||
Properties = {
|
Properties = {
|
||||||
{ new XmlName (null, "Baz"), node },
|
{ new XmlName (null, "Baz"), node },
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
||||||
var bindable = new Bindable ();
|
var bindable = new Bindable ();
|
||||||
|
|
||||||
Assert.IsNull (bindable.Baz);
|
Assert.IsNull (bindable.Baz);
|
||||||
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
|
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
|
||||||
Properties = {
|
Properties = {
|
||||||
{ new XmlName (null, "Baz"), node },
|
{ new XmlName (null, "Baz"), node },
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
||||||
var bindable = new Bindable ();
|
var bindable = new Bindable ();
|
||||||
|
|
||||||
Assert.IsNull (bindable.Foo);
|
Assert.IsNull (bindable.Foo);
|
||||||
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
|
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
|
||||||
Properties = {
|
Properties = {
|
||||||
{ new XmlName (null, "Foo"), node },
|
{ new XmlName (null, "Foo"), node },
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
||||||
var bindable = new Bindable ();
|
var bindable = new Bindable ();
|
||||||
|
|
||||||
Assert.IsNull (bindable.Bar);
|
Assert.IsNull (bindable.Bar);
|
||||||
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
|
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
|
||||||
Properties = {
|
Properties = {
|
||||||
{ new XmlName (null, "Bar"), node },
|
{ new XmlName (null, "Bar"), node },
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
||||||
var bindable = new Bindable ();
|
var bindable = new Bindable ();
|
||||||
|
|
||||||
Assert.IsNull (Bindable.GetQux (bindable));
|
Assert.IsNull (Bindable.GetQux (bindable));
|
||||||
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
|
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
|
||||||
Properties = {
|
Properties = {
|
||||||
{ new XmlName ("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable.Qux"), node },
|
{ new XmlName ("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable.Qux"), node },
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
||||||
var bindable = new Bindable ();
|
var bindable = new Bindable ();
|
||||||
|
|
||||||
Assert.IsNull (bindable.FooBar);
|
Assert.IsNull (bindable.FooBar);
|
||||||
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
|
var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
|
||||||
Properties = {
|
Properties = {
|
||||||
{ new XmlName (null, "FooBar"), node },
|
{ new XmlName (null, "FooBar"), node },
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,6 +334,7 @@
|
||||||
<Compile Include="McIgnorable.xaml.cs">
|
<Compile Include="McIgnorable.xaml.cs">
|
||||||
<DependentUpon>McIgnorable.xaml</DependentUpon>
|
<DependentUpon>McIgnorable.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="XamlLoaderCreateTests.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<Import Project="..\.nuspec\Xamarin.Forms.Debug.targets" />
|
<Import Project="..\.nuspec\Xamarin.Forms.Debug.targets" />
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace Xamarin.Forms.Xaml.UnitTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class XamlLoaderCreateTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void CreateFromXaml ()
|
||||||
|
{
|
||||||
|
var xaml = @"
|
||||||
|
<ContentView xmlns=""http://xamarin.com/schemas/2014/forms""
|
||||||
|
xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
|
||||||
|
x:Class=""Xamarin.Forms.Xaml.UnitTests.FOO"">
|
||||||
|
<Label Text=""Foo"" x:Name=""label""/>
|
||||||
|
</ContentView>";
|
||||||
|
|
||||||
|
var view = XamlLoader.Create (xaml);
|
||||||
|
Assert.That (view, Is.TypeOf<ContentView> ());
|
||||||
|
Assert.AreEqual ("Foo", ((Label)((ContentView)view).Content).Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CreateFromXamlDoesntFailOnMissingEventHandler ()
|
||||||
|
{
|
||||||
|
var xaml = @"
|
||||||
|
<Button xmlns=""http://xamarin.com/schemas/2014/forms""
|
||||||
|
xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
|
||||||
|
Clicked=""handleClick"">
|
||||||
|
</Button>";
|
||||||
|
|
||||||
|
Button button = null;
|
||||||
|
Assert.DoesNotThrow (() => button = XamlLoader.Create (xaml, true) as Button);
|
||||||
|
Assert.NotNull (button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -307,19 +307,25 @@ namespace Xamarin.Forms.Xaml
|
||||||
if (eventInfo != null && value is string)
|
if (eventInfo != null && value is string)
|
||||||
{
|
{
|
||||||
var methodInfo = rootElement.GetType().GetRuntimeMethods().FirstOrDefault(mi => mi.Name == (string)value);
|
var methodInfo = rootElement.GetType().GetRuntimeMethods().FirstOrDefault(mi => mi.Name == (string)value);
|
||||||
if (methodInfo == null)
|
if (methodInfo == null) {
|
||||||
{
|
var xpe = new XamlParseException (string.Format ("No method {0} found on type {1}", value, rootElement.GetType ()), lineInfo);
|
||||||
throw new XamlParseException(string.Format("No method {0} found on type {1}", value, rootElement.GetType()),
|
if (context.DoNotThrowOnExceptions) {
|
||||||
lineInfo);
|
System.Diagnostics.Debug.WriteLine (xpe.Message);
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
throw xpe;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
eventInfo.AddEventHandler(xamlelement, methodInfo.CreateDelegate(eventInfo.EventHandlerType, rootElement));
|
eventInfo.AddEventHandler(xamlelement, methodInfo.CreateDelegate(eventInfo.EventHandlerType, rootElement));
|
||||||
}
|
}
|
||||||
catch (ArgumentException)
|
catch (ArgumentException)
|
||||||
{
|
{
|
||||||
throw new XamlParseException(string.Format("Method {0} does not have the correct signature", value), lineInfo);
|
var xpe = new XamlParseException (string.Format ("Method {0} does not have the correct signature", value), lineInfo);
|
||||||
|
if (context.DoNotThrowOnExceptions)
|
||||||
|
System.Diagnostics.Debug.WriteLine (xpe.Message);
|
||||||
|
else
|
||||||
|
throw xpe;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -416,6 +422,9 @@ namespace Xamarin.Forms.Xaml
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context.DoNotThrowOnExceptions)
|
||||||
|
System.Diagnostics.Debug.WriteLine (exception.Message);
|
||||||
|
else
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace Xamarin.Forms.Xaml
|
||||||
return;
|
return;
|
||||||
|
|
||||||
XamlParseException xpe;
|
XamlParseException xpe;
|
||||||
var type = XamlParser.GetElementType(node.XmlType, node, Context.RootElement.GetType().GetTypeInfo().Assembly,
|
var type = XamlParser.GetElementType(node.XmlType, node, Context.RootElement?.GetType().GetTypeInfo().Assembly,
|
||||||
out xpe);
|
out xpe);
|
||||||
if (xpe != null)
|
if (xpe != null)
|
||||||
throw xpe;
|
throw xpe;
|
||||||
|
|
|
@ -18,5 +18,7 @@ namespace Xamarin.Forms.Xaml
|
||||||
public HydratationContext ParentContext { get; set; }
|
public HydratationContext ParentContext { get; set; }
|
||||||
|
|
||||||
public BindableObject RootElement { get; set; }
|
public BindableObject RootElement { get; set; }
|
||||||
|
|
||||||
|
public bool DoNotThrowOnExceptions { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -62,25 +62,55 @@ namespace Xamarin.Forms.Xaml
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rootnode = new RuntimeRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), view);
|
var rootnode = new RuntimeRootNode (new XmlType (reader.NamespaceURI, reader.Name, null), view, (IXmlNamespaceResolver)reader);
|
||||||
|
XamlParser.ParseXaml (rootnode, reader);
|
||||||
XamlParser.ParseXaml(rootnode, reader);
|
Visit (rootnode, new HydratationContext { RootElement = view });
|
||||||
|
|
||||||
var visitorContext = new HydratationContext { RootElement = view };
|
|
||||||
|
|
||||||
rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null);
|
|
||||||
//set parents for {StaticResource}
|
|
||||||
rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null);
|
|
||||||
rootnode.Accept(new NamescopingVisitor(visitorContext), null); //set namescopes for {x:Reference}
|
|
||||||
rootnode.Accept(new CreateValuesVisitor(visitorContext), null);
|
|
||||||
rootnode.Accept(new RegisterXNamesVisitor(visitorContext), null);
|
|
||||||
rootnode.Accept(new FillResourceDictionariesVisitor(visitorContext), null);
|
|
||||||
rootnode.Accept(new ApplyPropertiesVisitor(visitorContext, true), null);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static object Create (string xaml, bool doNotThrow = false)
|
||||||
|
{
|
||||||
|
object inflatedView = null;
|
||||||
|
using (var reader = XmlReader.Create (new StringReader (xaml))) {
|
||||||
|
while (reader.Read ()) {
|
||||||
|
//Skip until element
|
||||||
|
if (reader.NodeType == XmlNodeType.Whitespace)
|
||||||
|
continue;
|
||||||
|
if (reader.NodeType != XmlNodeType.Element) {
|
||||||
|
Debug.WriteLine ("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rootnode = new RuntimeRootNode (new XmlType (reader.NamespaceURI, reader.Name, null), null, (IXmlNamespaceResolver)reader);
|
||||||
|
XamlParser.ParseXaml (rootnode, reader);
|
||||||
|
var visitorContext = new HydratationContext {
|
||||||
|
DoNotThrowOnExceptions = doNotThrow,
|
||||||
|
};
|
||||||
|
var cvv = new CreateValuesVisitor (visitorContext);
|
||||||
|
cvv.Visit ((ElementNode)rootnode, null);
|
||||||
|
inflatedView = rootnode.Root = visitorContext.Values [rootnode];
|
||||||
|
visitorContext.RootElement = inflatedView as BindableObject;
|
||||||
|
|
||||||
|
Visit (rootnode, visitorContext);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inflatedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Visit (RootNode rootnode, HydratationContext visitorContext)
|
||||||
|
{
|
||||||
|
rootnode.Accept (new XamlNodeVisitor ((node, parent) => node.Parent = parent), null); //set parents for {StaticResource}
|
||||||
|
rootnode.Accept (new ExpandMarkupsVisitor (visitorContext), null);
|
||||||
|
rootnode.Accept (new NamescopingVisitor (visitorContext), null); //set namescopes for {x:Reference}
|
||||||
|
rootnode.Accept (new CreateValuesVisitor (visitorContext), null);
|
||||||
|
rootnode.Accept (new RegisterXNamesVisitor (visitorContext), null);
|
||||||
|
rootnode.Accept (new FillResourceDictionariesVisitor (visitorContext), null);
|
||||||
|
rootnode.Accept (new ApplyPropertiesVisitor (visitorContext, true), null);
|
||||||
|
}
|
||||||
|
|
||||||
static string GetXamlForType(Type type)
|
static string GetXamlForType(Type type)
|
||||||
{
|
{
|
||||||
var assembly = type.GetTypeInfo().Assembly;
|
var assembly = type.GetTypeInfo().Assembly;
|
||||||
|
@ -197,12 +227,12 @@ namespace Xamarin.Forms.Xaml
|
||||||
|
|
||||||
public class RuntimeRootNode : RootNode
|
public class RuntimeRootNode : RootNode
|
||||||
{
|
{
|
||||||
public RuntimeRootNode(XmlType xmlType, object root) : base(xmlType)
|
public RuntimeRootNode(XmlType xmlType, object root, IXmlNamespaceResolver resolver) : base (xmlType, resolver)
|
||||||
{
|
{
|
||||||
Root = root;
|
Root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Root { get; private set; }
|
public object Root { get; internal set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -178,7 +178,7 @@ namespace Xamarin.Forms.Xaml
|
||||||
|
|
||||||
internal abstract class RootNode : ElementNode
|
internal abstract class RootNode : ElementNode
|
||||||
{
|
{
|
||||||
protected RootNode(XmlType xmlType) : base(xmlType, xmlType.NamespaceUri, null)
|
protected RootNode(XmlType xmlType, IXmlNamespaceResolver nsResolver) : base(xmlType, xmlType.NamespaceUri, nsResolver)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче