Browse Source

Support default clr-namespace when loading XAML from Uri or previewer

pull/1389/head
Nikita Tsukanov 8 years ago
parent
commit
fee5b4e594
  1. 2
      samples/ControlCatalog/MainWindow.xaml
  2. 2
      src/Avalonia.Base/Platform/IAssetLoader.cs
  3. 4
      src/Avalonia.DesignerSupport/DesignWindowLoader.cs
  4. 2
      src/Avalonia.DesignerSupport/DesignerAssist.cs
  5. 1
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  6. 11
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
  7. 27
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoaderPortableXaml.cs
  8. 20
      src/Shared/PlatformSupport/AssetLoader.cs
  9. 5
      tests/Avalonia.UnitTests/MockAssetLoader.cs

2
samples/ControlCatalog/MainWindow.xaml

@ -1,6 +1,6 @@
<Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300"
Title="Avalonia Control Gallery"
Icon="resm:ControlCatalog.Assets.test_icon.ico?assembly=ControlCatalog"
xmlns:local="clr-namespace:ControlCatalog;assembly=ControlCatalog">
xmlns:local="clr-namespace:ControlCatalog">
<local:MainView/>
</Window>

2
src/Avalonia.Base/Platform/IAssetLoader.cs

@ -43,5 +43,7 @@ namespace Avalonia.Platform
/// The resource was not found.
/// </exception>
Stream Open(Uri uri, Uri baseUri = null);
Tuple<Assembly, Stream> OpenWithAssembly(Uri uri, Uri baseUri = null);
}
}

4
src/Avalonia.DesignerSupport/DesignWindowLoader.cs

@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
@ -30,7 +31,8 @@ namespace Avalonia.DesignerSupport
new Uri("resm:Fake.xaml?assembly=" + Path.GetFileNameWithoutExtension(assemblyPath));
}
var loaded = loader.Load(stream, null, baseUri);
var localAsm = assemblyPath != null ? Assembly.LoadFile(assemblyPath) : null;
var loaded = loader.Load(stream, localAsm, null, baseUri);
var styles = loaded as Styles;
if (styles != null)
{

2
src/Avalonia.DesignerSupport/DesignerAssist.cs

@ -24,7 +24,7 @@ namespace Avalonia.DesignerSupport
var loader = new AvaloniaXamlLoader();
var baseLight = (IStyle)loader.Load(
new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"));
new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"), null);
Styles.Add(baseLight);
}
}

1
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -30,7 +30,6 @@
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AvaloniaXamlLoaderPortableXaml.cs" />
<Compile Include="AvaloniaXamlLoader.cs" />
<Compile Include="Converters\MatrixTypeConverter.cs" />
<Compile Include="Converters\RectTypeConverter.cs" />
<Compile Include="Converters\SetterValueTypeConverter.cs" />

11
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs

@ -1,11 +0,0 @@
namespace Avalonia.Markup.Xaml
{
public class AvaloniaXamlLoader : AvaloniaXamlLoaderPortableXaml
{
public static object Parse(string xaml)
=> new AvaloniaXamlLoader().Load(xaml);
public static T Parse<T>(string xaml)
=> (T)Parse(xaml);
}
}

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

@ -17,7 +17,7 @@ namespace Avalonia.Markup.Xaml
/// <summary>
/// Loads XAML for a avalonia application.
/// </summary>
public class AvaloniaXamlLoaderPortableXaml
public class AvaloniaXamlLoader
{
private readonly AvaloniaXamlSchemaContext _context = GetContext();
@ -40,7 +40,7 @@ namespace Avalonia.Markup.Xaml
/// <summary>
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
/// </summary>
public AvaloniaXamlLoaderPortableXaml()
public AvaloniaXamlLoader()
{
}
@ -89,7 +89,7 @@ namespace Avalonia.Markup.Xaml
initialize?.BeginInit();
try
{
return Load(stream, rootInstance, uri);
return Load(stream, type.Assembly, rootInstance, uri);
}
finally
{
@ -125,11 +125,12 @@ namespace Avalonia.Markup.Xaml
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?");
}
using (var stream = assetLocator.Open(uri, baseUri))
var asset = assetLocator.OpenWithAssembly(uri, baseUri);
using (var stream = asset.Item2)
{
try
{
return Load(stream, rootInstance, uri);
return Load(stream, asset.Item1, rootInstance, uri);
}
catch (Exception e)
{
@ -147,17 +148,18 @@ namespace Avalonia.Markup.Xaml
/// Loads XAML from a string.
/// </summary>
/// <param name="xaml">The string containing the XAML.</param>
/// <param name="localAssembly">Default assembly for clr-namespace:</param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <returns>The loaded object.</returns>
public object Load(string xaml, object rootInstance = null)
public object Load(string xaml, Assembly localAssembly, object rootInstance = null)
{
Contract.Requires<ArgumentNullException>(xaml != null);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml)))
{
return Load(stream, rootInstance);
return Load(stream, localAssembly, rootInstance);
}
}
@ -165,17 +167,18 @@ namespace Avalonia.Markup.Xaml
/// Loads XAML from a stream.
/// </summary>
/// <param name="stream">The stream containing the XAML.</param>
/// <param name="localAssembly">Default assembly for clr-namespace</param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <param name="uri">The URI of the XAML</param>
/// <returns>The loaded object.</returns>
public object Load(Stream stream, object rootInstance = null, Uri uri = null)
public object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null)
{
var readerSettings = new XamlXmlReaderSettings()
{
BaseUri = uri,
LocalAssembly = rootInstance?.GetType().GetTypeInfo().Assembly
LocalAssembly = localAssembly
};
var reader = new XamlXmlReader(stream, _context, readerSettings);
@ -223,5 +226,11 @@ namespace Avalonia.Markup.Xaml
yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm);
yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm);
}
public static object Parse(string xaml, Assembly localAssembly = null)
=> new AvaloniaXamlLoader().Load(xaml, localAssembly);
public static T Parse<T>(string xaml, Assembly localAssembly)
=> (T)Parse(xaml, localAssembly);
}
}

20
src/Shared/PlatformSupport/AssetLoader.cs

@ -67,7 +67,20 @@ namespace Avalonia.Shared.PlatformSupport
/// <exception cref="FileNotFoundException">
/// The resource was not found.
/// </exception>
public Stream Open(Uri uri, Uri baseUri = null)
public Stream Open(Uri uri, Uri baseUri = null) => OpenWithAssembly(uri, baseUri).Item2;
/// <summary>
/// Opens the resource with the requested URI.
/// </summary>
/// <param name="uri">The URI.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <returns>An assembly (optional) and a stream containing the resource contents.</returns>
/// <exception cref="FileNotFoundException">
/// The resource was not found.
/// </exception>
public Tuple<Assembly, Stream> OpenWithAssembly(Uri uri, Uri baseUri = null)
{
var asset = GetAsset(uri, baseUri);
@ -76,7 +89,7 @@ namespace Avalonia.Shared.PlatformSupport
throw new FileNotFoundException($"The resource {uri} could not be found.");
}
return asset.GetStream();
return Tuple.Create(asset.Assembly, asset.GetStream());
}
private IAssetDescriptor GetAsset(Uri uri, Uri baseUri)
@ -162,6 +175,7 @@ namespace Avalonia.Shared.PlatformSupport
private interface IAssetDescriptor
{
Stream GetStream();
Assembly Assembly { get; }
}
private class AssemblyResourceDescriptor : IAssetDescriptor
@ -179,6 +193,8 @@ namespace Avalonia.Shared.PlatformSupport
{
return _asm.GetManifestResourceStream(_name);
}
public Assembly Assembly => _asm;
}
private class AssemblyDescriptor

5
tests/Avalonia.UnitTests/MockAssetLoader.cs

@ -27,6 +27,11 @@ namespace Avalonia.UnitTests
{
return new MemoryStream(Encoding.UTF8.GetBytes(_assets[uri]));
}
public Tuple<Assembly, Stream> OpenWithAssembly(Uri uri, Uri baseUri = null)
{
return Tuple.Create((Assembly) null, Open(uri, baseUri));
}
public void SetDefaultAssembly(Assembly asm)
{

Loading…
Cancel
Save