Browse Source

Get rid of AvaloniaXamlLoader.UriContext, now context is passed to Extensions and Type converters so it can be used

pull/916/head
Andrey Kunchev 10 years ago
parent
commit
3e23c0d05f
  1. 2
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  2. 65
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoaderPortableXaml.cs
  3. 29
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleIncludeExtension.cs
  4. 24
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlContext.cs
  5. 21
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs
  6. 23
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs
  7. 16
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs
  8. 42
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/TypeDescriptorExtensions.cs
  9. 16
      src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs

2
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -53,6 +53,8 @@
<Compile Include="AvaloniaXamlLoaderPortableXaml.cs" />
<Compile Include="AvaloniaXamlLoader.cs" />
<Compile Include="Converters\SetterValueTypeConverter.cs" />
<Compile Include="MarkupExtensions\StyleIncludeExtension.cs" />
<Compile Include="PortableXaml\AvaloniaXamlContext.cs" />
<Compile Include="PortableXaml\XamlBinding.cs" />
<Compile Include="PortableXaml\AttributeExtensions.cs" />
<Compile Include="PortableXaml\AvaloniaMemberAttributeProvider.cs" />

65
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoaderPortableXaml.cs

@ -2,7 +2,6 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Controls;
using Avalonia.Markup.Xaml.Context;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Markup.Xaml.PortableXaml;
using Avalonia.Platform;
@ -45,21 +44,6 @@ namespace Avalonia.Markup.Xaml
{
}
/// <summary>
/// Gets the URI of the XAML file currently being loaded.
/// </summary>
/// <remarks>
/// TODO: Making this internal for now as I'm not sure that this is the correct
/// thing to do, but its needed by <see cref="StyleInclude"/> to get the URL of
/// the currently loading XAML file, as we can't use the OmniXAML parsing context
/// there. Maybe we need a way to inject OmniXAML context into the objects its
/// constructing?
/// </remarks>
[Obsolete]
internal static Uri UriContext => s_uriStack.Count > 0 ? s_uriStack.Peek() : null;
private static Stack<Uri> s_uriStack = new Stack<Uri>();
/// <summary>
/// Loads the XAML into a Avalonia component.
/// </summary>
@ -176,47 +160,34 @@ namespace Avalonia.Markup.Xaml
/// <returns>The loaded object.</returns>
public object Load(Stream stream, object rootInstance = null, Uri uri = null)
{
try
var readerSettings = new XamlXmlReaderSettings()
{
if (uri != null)
{
s_uriStack.Push(uri);
}
var readerSettings = new XamlXmlReaderSettings();
Type type = rootInstance?.GetType();
if (type != null)
{
readerSettings.LocalAssembly = type.GetTypeInfo().Assembly;
}
BaseUri = uri,
LocalAssembly = rootInstance?.GetType().GetTypeInfo().Assembly
};
var reader = new XamlXmlReader(stream, _context, readerSettings);
var reader = new XamlXmlReader(stream, _context, readerSettings);
object result = LoadFromReader(reader, rootInstance);
object result = LoadFromReader(reader, rootInstance, readerSettings);
var topLevel = result as TopLevel;
var topLevel = result as TopLevel;
if (topLevel != null)
{
DelayedBinding.ApplyBindings(topLevel);
}
return result;
}
finally
if (topLevel != null)
{
if (uri != null)
{
s_uriStack.Pop();
}
DelayedBinding.ApplyBindings(topLevel);
}
return result;
}
internal static object LoadFromReader(XamlReader reader, object instance)
internal static object LoadFromReader(XamlReader reader,
object instance,
AvaloniaXamlContext context = null)
{
var writer = AvaloniaXamlObjectWriter.Create(reader.SchemaContext, instance);
var writer = AvaloniaXamlObjectWriter.Create(
reader.SchemaContext,
instance,
context);
XamlServices.Transform(reader, writer);

29
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleIncludeExtension.cs

@ -0,0 +1,29 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling;
using Portable.Xaml;
using Portable.Xaml.ComponentModel;
using Portable.Xaml.Markup;
using System;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
[MarkupExtensionReturnType(typeof(IStyle))]
public class StyleIncludeExtension : MarkupExtension
{
public StyleIncludeExtension()
{
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var tdc = (ITypeDescriptorContext)serviceProvider;
return new StyleInclude(tdc.GetBaseUri()) { Source = Source };
}
public Uri Source { get; set; }
}
}

24
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlContext.cs

@ -0,0 +1,24 @@
using Portable.Xaml;
using System;
using System.Reflection;
namespace Avalonia.Markup.Xaml.PortableXaml
{
public class AvaloniaXamlContext
{
internal AvaloniaXamlContext(Uri baseUri, Assembly localAssembly)
{
LocalAssembly = localAssembly;
BaseUri = baseUri;
}
public Assembly LocalAssembly { get; }
public Uri BaseUri { get; }
public static implicit operator AvaloniaXamlContext(XamlXmlReaderSettings sett)
{
return new AvaloniaXamlContext(sett.BaseUri, sett.LocalAssembly);
}
}
}

21
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs

@ -1,5 +1,6 @@
using Avalonia.Data;
using Portable.Xaml;
using Portable.Xaml.ComponentModel;
using System.Collections.Generic;
using System.Linq;
@ -7,15 +8,23 @@ namespace Avalonia.Markup.Xaml.PortableXaml
{
public class AvaloniaXamlObjectWriter : XamlObjectWriter
{
public static AvaloniaXamlObjectWriter Create(XamlSchemaContext schemaContext, object instance)
public static AvaloniaXamlObjectWriter Create(
XamlSchemaContext schemaContext,
object instance,
AvaloniaXamlContext context)
{
var writerSettings = new XamlObjectWriterSettings();
var nameScope = new AvaloniaNameScope { Instance = instance };
writerSettings.ExternalNameScope = nameScope;
writerSettings.RegisterNamesOnExternalNamescope = true;
writerSettings.RootObjectInstance = instance;
return new AvaloniaXamlObjectWriter(schemaContext, writerSettings, nameScope);
var writerSettings = new XamlObjectWriterSettings()
{
ExternalNameScope = nameScope,
RegisterNamesOnExternalNamescope = true,
RootObjectInstance = instance
};
return new AvaloniaXamlObjectWriter(schemaContext,
writerSettings.WithContext(context),
nameScope);
}
private readonly DelayedValuesHelper _delayedValuesHelper = new DelayedValuesHelper();

23
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs

@ -1,12 +1,14 @@
using Avalonia.Data;
using Avalonia.Markup.Xaml.Context;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Markup.Xaml.Styling;
using Portable.Xaml;
using Portable.Xaml.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using am = Avalonia.Metadata;
namespace Avalonia.Markup.Xaml.PortableXaml
{
@ -19,7 +21,7 @@ namespace Avalonia.Markup.Xaml.PortableXaml
private AvaloniaXamlSchemaContext(IRuntimeTypeProvider typeProvider)
//better not set the references assemblies
//TODO: check this on iOS
//TODO: check this on iOS
//: base(typeProvider.ReferencedAssemblies)
{
Contract.Requires<ArgumentNullException>(typeProvider != null);
@ -150,16 +152,27 @@ namespace Avalonia.Markup.Xaml.PortableXaml
return result;
}
private static readonly Dictionary<Type, Type> _wellKnownExtensionTypes = new Dictionary<Type, Type>()
{
{ typeof(Binding), typeof(BindingExtension) },
{ typeof(StyleInclude), typeof(StyleIncludeExtension) },
};
private XamlType GetAvaloniaXamlType(Type type)
{
Type extType;
_wellKnownExtensionTypes.TryGetValue(type, out extType);
if (typeof(IBinding).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
{
return BindingXamlType.Create(type, this);
return new BindingXamlType(extType ?? type, this);
}
if (typeof(AvaloniaObject).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
if (extType != null ||
typeof(AvaloniaObject).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
{
return new AvaloniaXamlType(type, this);
return new AvaloniaXamlType(extType ?? type, this);
}
return null;

16
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs

@ -1,7 +1,6 @@
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Metadata;
using Avalonia.Styling;
using Portable.Xaml;
@ -48,24 +47,13 @@ namespace Avalonia.Markup.Xaml.PortableXaml
public class BindingXamlType : XamlType
{
public static BindingXamlType Create(Type type, XamlSchemaContext schemaContext)
{
if (type == typeof(Binding))
{
//in xaml we need to use the extension
type = typeof(BindingExtension);
}
return new BindingXamlType(type, schemaContext);
}
private static List<Type> _notAssignable =
new List<Type>
{
typeof (IXmlSerializable)
};
private BindingXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
public BindingXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
base(underlyingType, schemaContext)
{
}
@ -194,7 +182,7 @@ namespace Avalonia.Markup.Xaml.PortableXaml
{
//can't make it work to assign TypeConverter to Setter.Value
//so we need it hard coded
//TODO: try to assosiate TypeConverter with Setter.Value
//TODO: try to assosiate TypeConverter with Setter.Value
//and remove this lines
if (instance is Setter &&
Member.Name == nameof(Setter.Value) &&

42
src/Markup/Avalonia.Markup.Xaml/PortableXaml/TypeDescriptorExtensions.cs

@ -1,7 +1,9 @@
using System;
using Avalonia.Markup.Xaml.PortableXaml;
using Portable.Xaml.Markup;
using System.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Portable.Xaml.ComponentModel
{
@ -56,5 +58,41 @@ namespace Portable.Xaml.ComponentModel
return amb.GetAllAmbientValues(sc.GetXamlType(typeof(T))).OfType<T>();
}
public static Uri GetBaseUri(this ITypeDescriptorContext ctx)
{
return ctx.GetWriterSettings()?.Context.BaseUri;
}
public static Assembly GetLocalAssembly(this ITypeDescriptorContext ctx)
{
return ctx.GetWriterSettings()?.Context.LocalAssembly;
}
public static AvaloniaXamlContext GetAvaloniaXamlContext(this ITypeDescriptorContext ctx)
{
return ctx.GetWriterSettings()?.Context;
}
public static XamlObjectWriterSettings WithContext(this XamlObjectWriterSettings settings, AvaloniaXamlContext context)
{
return new AvaloniaXamlObjectWriterSettings(settings, context);
}
private static AvaloniaXamlObjectWriterSettings GetWriterSettings(this ITypeDescriptorContext ctx)
{
return ctx.GetService<IXamlObjectWriterFactory>().GetParentSettings() as AvaloniaXamlObjectWriterSettings;
}
private class AvaloniaXamlObjectWriterSettings : XamlObjectWriterSettings
{
public AvaloniaXamlObjectWriterSettings(XamlObjectWriterSettings settings, AvaloniaXamlContext context)
: base(settings)
{
Context = context;
}
public AvaloniaXamlContext Context { get; }
}
}
}

16
src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs

@ -1,8 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Avalonia.Styling;
using System;
namespace Avalonia.Markup.Xaml.Styling
{
@ -17,6 +17,9 @@ namespace Avalonia.Markup.Xaml.Styling
/// <summary>
/// Initializes a new instance of the <see cref="StyleInclude"/> class.
/// </summary>
/// <param name="baseUri"></param>
#if OMNIXAML
public StyleInclude()
{
// StyleInclude will usually be loaded from XAML and its URI can be relative to the
@ -25,6 +28,15 @@ namespace Avalonia.Markup.Xaml.Styling
_baseUri = AvaloniaXamlLoader.UriContext;
}
#else
public StyleInclude(Uri baseUri)
{
_baseUri = baseUri;
}
#endif
/// <summary>
/// Gets or sets the source URL.
/// </summary>
@ -68,4 +80,4 @@ namespace Avalonia.Markup.Xaml.Styling
return Loaded.FindResource(name);
}
}
}
}
Loading…
Cancel
Save