From 3bec8036a7cb1eb85325da78d5be8404cea6a252 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Tue, 22 May 2018 22:45:53 +0200 Subject: [PATCH 1/3] Initial --- src/Avalonia.Base/Platform/IAssetLoader.cs | 24 ++++--- src/Shared/PlatformSupport/AssetLoader.cs | 70 ++++++++++++++------- tests/Avalonia.UnitTests/MockAssetLoader.cs | 13 ++-- 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/Avalonia.Base/Platform/IAssetLoader.cs b/src/Avalonia.Base/Platform/IAssetLoader.cs index ba30af60bf..3b459818dd 100644 --- a/src/Avalonia.Base/Platform/IAssetLoader.cs +++ b/src/Avalonia.Base/Platform/IAssetLoader.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Collections.Generic; using System.IO; using System.Reflection; @@ -18,8 +19,8 @@ namespace Avalonia.Platform /// AssetLoader needs a refactor cause right now it lives in 3+ platforms which /// can all be loaded on Windows. /// - /// - void SetDefaultAssembly(Assembly asm); + /// + void SetDefaultAssembly(Assembly assembly); /// /// Checks if an asset with the specified URI exists. @@ -32,32 +33,39 @@ namespace Avalonia.Platform bool Exists(Uri uri, Uri baseUri = null); /// - /// Opens the resource with the requested URI. + /// Opens the asset with the requested URI. /// /// The URI. /// /// A base URI to use if is relative. /// - /// A stream containing the resource contents. + /// A stream containing the asset contents. /// /// The resource was not found. /// Stream Open(Uri uri, Uri baseUri = null); /// - /// Opens the resource with the requested URI and returns the resource string and the - /// assembly containing the resource. + /// Opens the asset with the requested URI and returns the asset stream and the + /// assembly containing the asset. /// /// The URI. /// /// A base URI to use if is relative. /// /// - /// The stream containing the resource contents together with the assembly. + /// The stream containing the asset contents together with the assembly. /// /// /// The resource was not found. /// - Tuple OpenAndGetAssembly(Uri uri, Uri baseUri = null); + (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null); + + /// + /// Gets all assets at a specific location. + /// + /// The location of assets. + /// A tuple containing the absolute path to the resource and the owner assembly + IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location); } } diff --git a/src/Shared/PlatformSupport/AssetLoader.cs b/src/Shared/PlatformSupport/AssetLoader.cs index fa11edb57b..b835170036 100644 --- a/src/Shared/PlatformSupport/AssetLoader.cs +++ b/src/Shared/PlatformSupport/AssetLoader.cs @@ -10,6 +10,7 @@ using Avalonia.Platform; namespace Avalonia.Shared.PlatformSupport { + /// /// /// Loads assets compiled into the application binary. /// @@ -34,21 +35,26 @@ namespace Avalonia.Shared.PlatformSupport _defaultAssembly = new AssemblyDescriptor(assembly); } + /// /// - /// Sets the default assembly from which to load assets for which no assembly is specified. + /// We need a way to override the default assembly selected by the host platform + /// because right now it is selecting the wrong one for PCL based Apps. The + /// AssetLoader needs a refactor cause right now it lives in 3+ platforms which + /// can all be loaded on Windows. /// - /// The default assembly. + /// public void SetDefaultAssembly(Assembly assembly) { _defaultAssembly = new AssemblyDescriptor(assembly); } + /// /// /// Checks if an asset with the specified URI exists. /// /// The URI. /// - /// A base URI to use if is relative. + /// A base URI to use if is relative. /// /// True if the asset could be found; otherwise false. public bool Exists(Uri uri, Uri baseUri = null) @@ -56,34 +62,37 @@ namespace Avalonia.Shared.PlatformSupport return GetAsset(uri, baseUri) != null; } + /// /// - /// Opens the resource with the requested URI. + /// Opens the asset with the requested URI. /// /// The URI. /// - /// A base URI to use if is relative. + /// A base URI to use if is relative. /// - /// A stream containing the resource contents. - /// + /// A stream containing the asset contents. + /// /// The resource was not found. /// - public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).Item1; - + public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).stream; + + + /// /// - /// Opens the resource with the requested URI and returns the resource string and the - /// assembly containing the resource. + /// Opens the asset with the requested URI and returns the asset stream and the + /// assembly containing the asset. /// /// The URI. /// - /// A base URI to use if is relative. + /// A base URI to use if is relative. /// /// - /// The stream containing the resource contents together with the assembly. + /// The stream containing the asset contents together with the assembly. /// - /// + /// /// The resource was not found. /// - public Tuple OpenAndGetAssembly(Uri uri, Uri baseUri = null) + public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null) { var asset = GetAsset(uri, baseUri); @@ -92,7 +101,22 @@ namespace Avalonia.Shared.PlatformSupport throw new FileNotFoundException($"The resource {uri} could not be found."); } - return Tuple.Create(asset.GetStream(), asset.Assembly); + return (asset.GetStream(), asset.Assembly); + } + + /// + /// + /// Gets all assets at a specific location. + /// + /// The location of assets. + /// A tuple containing the absolute path to the resource and the owner assembly + public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location) + { + var assembly = GetAssembly(location); + + return assembly?.Assets.Where(x => x.Key.Contains(location.AbsolutePath)) + .Select(x => (x.Key, x.Value.Assembly)) ?? + Enumerable.Empty<(string AbsolutePath, Assembly Assembly)>(); } private IAssetDescriptor GetAsset(Uri uri, Uri baseUri) @@ -110,8 +134,8 @@ namespace Avalonia.Shared.PlatformSupport IAssetDescriptor rv; - var resourceKey = uri.AbsolutePath; - asm.Resources.TryGetValue(resourceKey, out rv); + var assetKey = uri.AbsolutePath; + asm.Assets.TryGetValue(assetKey, out rv); return rv; } throw new ArgumentException($"Invalid uri, see https://github.com/AvaloniaUI/Avalonia/issues/282#issuecomment-166982104", nameof(uri)); @@ -122,9 +146,8 @@ namespace Avalonia.Shared.PlatformSupport if (uri != null) { var qs = ParseQueryString(uri); - string assemblyName; - if (qs.TryGetValue("assembly", out assemblyName)) + if (qs.TryGetValue("assembly", out var assemblyName)) { return GetAssembly(assemblyName); } @@ -140,8 +163,7 @@ namespace Avalonia.Shared.PlatformSupport return _defaultAssembly; } - AssemblyDescriptor rv; - if (!AssemblyNameCache.TryGetValue(name, out rv)) + if (!AssemblyNameCache.TryGetValue(name, out var rv)) { var loadedAssemblies = AvaloniaLocator.Current.GetService().GetLoadedAssemblies(); var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name); @@ -208,14 +230,14 @@ namespace Avalonia.Shared.PlatformSupport if (assembly != null) { - Resources = assembly.GetManifestResourceNames() + Assets = assembly.GetManifestResourceNames() .ToDictionary(n => n, n => (IAssetDescriptor)new AssemblyResourceDescriptor(assembly, n)); Name = assembly.GetName().Name; } } public Assembly Assembly { get; } - public Dictionary Resources { get; } + public Dictionary Assets { get; } public string Name { get; } } } diff --git a/tests/Avalonia.UnitTests/MockAssetLoader.cs b/tests/Avalonia.UnitTests/MockAssetLoader.cs index d6b70aee16..abfac77a5e 100644 --- a/tests/Avalonia.UnitTests/MockAssetLoader.cs +++ b/tests/Avalonia.UnitTests/MockAssetLoader.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text; -using System.Threading.Tasks; using Avalonia.Platform; namespace Avalonia.UnitTests @@ -27,10 +26,16 @@ namespace Avalonia.UnitTests { return new MemoryStream(Encoding.UTF8.GetBytes(_assets[uri])); } - - public Tuple OpenAndGetAssembly(Uri uri, Uri baseUri = null) + + public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null) + { + return (Open(uri, baseUri), (Assembly)null); + } + + public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location) { - return Tuple.Create(Open(uri, baseUri), (Assembly)null); + return _assets.Keys.Where(x => x.AbsolutePath.Contains(location.AbsolutePath)) + .Select(x => (x.AbsolutePath, Assembly.GetEntryAssembly())); } public void SetDefaultAssembly(Assembly asm) From 724bb45abb8ce55d8dfea9d91a746f386990a2cd Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Wed, 23 May 2018 00:26:42 +0200 Subject: [PATCH 2/3] comment fixes --- src/Avalonia.Base/Platform/IAssetLoader.cs | 6 +++--- src/Shared/PlatformSupport/AssetLoader.cs | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Base/Platform/IAssetLoader.cs b/src/Avalonia.Base/Platform/IAssetLoader.cs index 3b459818dd..d3b6cafeae 100644 --- a/src/Avalonia.Base/Platform/IAssetLoader.cs +++ b/src/Avalonia.Base/Platform/IAssetLoader.cs @@ -41,7 +41,7 @@ namespace Avalonia.Platform /// /// A stream containing the asset contents. /// - /// The resource was not found. + /// The asset could not be found. /// Stream Open(Uri uri, Uri baseUri = null); @@ -57,7 +57,7 @@ namespace Avalonia.Platform /// The stream containing the asset contents together with the assembly. /// /// - /// The resource was not found. + /// The asset could not be found. /// (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null); @@ -65,7 +65,7 @@ namespace Avalonia.Platform /// Gets all assets at a specific location. /// /// The location of assets. - /// A tuple containing the absolute path to the resource and the owner assembly + /// A tuple containing the absolute path to the asset and the owner assembly IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location); } } diff --git a/src/Shared/PlatformSupport/AssetLoader.cs b/src/Shared/PlatformSupport/AssetLoader.cs index b835170036..0cf60a5e19 100644 --- a/src/Shared/PlatformSupport/AssetLoader.cs +++ b/src/Shared/PlatformSupport/AssetLoader.cs @@ -72,7 +72,7 @@ namespace Avalonia.Shared.PlatformSupport /// /// A stream containing the asset contents. /// - /// The resource was not found. + /// The asset could not be found. /// public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).stream; @@ -90,7 +90,7 @@ namespace Avalonia.Shared.PlatformSupport /// The stream containing the asset contents together with the assembly. /// /// - /// The resource was not found. + /// The asset could not be found. /// public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null) { @@ -98,7 +98,7 @@ namespace Avalonia.Shared.PlatformSupport if (asset == null) { - throw new FileNotFoundException($"The resource {uri} could not be found."); + throw new FileNotFoundException($"The asset {uri} could not be found."); } return (asset.GetStream(), asset.Assembly); @@ -114,6 +114,8 @@ namespace Avalonia.Shared.PlatformSupport { var assembly = GetAssembly(location); + var availableAssets = assembly?.Assets; + return assembly?.Assets.Where(x => x.Key.Contains(location.AbsolutePath)) .Select(x => (x.Key, x.Value.Assembly)) ?? Enumerable.Empty<(string AbsolutePath, Assembly Assembly)>(); @@ -129,7 +131,7 @@ namespace Avalonia.Shared.PlatformSupport { throw new ArgumentException( "No default assembly, entry assembly or explicit assembly specified; " + - "don't know where to look up for the resource, try specifiyng assembly explicitly."); + "don't know where to look up for the asset, try specifiyng assembly explicitly."); } IAssetDescriptor rv; From f609c9c5d99595c4749a5e5ad8c770886ce4e0fb Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Wed, 23 May 2018 01:46:16 +0200 Subject: [PATCH 3/3] Cleanup --- src/Avalonia.Base/Platform/IAssetLoader.cs | 8 +-- src/Shared/PlatformSupport/AssetLoader.cs | 62 +++++++++------------ tests/Avalonia.UnitTests/MockAssetLoader.cs | 4 +- 3 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/Avalonia.Base/Platform/IAssetLoader.cs b/src/Avalonia.Base/Platform/IAssetLoader.cs index d3b6cafeae..dda2cbc2d5 100644 --- a/src/Avalonia.Base/Platform/IAssetLoader.cs +++ b/src/Avalonia.Base/Platform/IAssetLoader.cs @@ -62,10 +62,10 @@ namespace Avalonia.Platform (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null); /// - /// Gets all assets at a specific location. + /// Gets all assets of a folder and subfolders that match specified uri. /// - /// The location of assets. - /// A tuple containing the absolute path to the asset and the owner assembly - IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location); + /// The URI. + /// All matching assets as a tuple of the absolute path to the asset and the assembly containing the asset + IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri uri); } } diff --git a/src/Shared/PlatformSupport/AssetLoader.cs b/src/Shared/PlatformSupport/AssetLoader.cs index 0cf60a5e19..b4d17b22a1 100644 --- a/src/Shared/PlatformSupport/AssetLoader.cs +++ b/src/Shared/PlatformSupport/AssetLoader.cs @@ -10,7 +10,6 @@ using Avalonia.Platform; namespace Avalonia.Shared.PlatformSupport { - /// /// /// Loads assets compiled into the application binary. /// @@ -35,26 +34,21 @@ namespace Avalonia.Shared.PlatformSupport _defaultAssembly = new AssemblyDescriptor(assembly); } - /// /// - /// We need a way to override the default assembly selected by the host platform - /// because right now it is selecting the wrong one for PCL based Apps. The - /// AssetLoader needs a refactor cause right now it lives in 3+ platforms which - /// can all be loaded on Windows. + /// Sets the default assembly from which to load assets for which no assembly is specified. /// - /// + /// The default assembly. public void SetDefaultAssembly(Assembly assembly) { _defaultAssembly = new AssemblyDescriptor(assembly); } - /// /// /// Checks if an asset with the specified URI exists. /// /// The URI. /// - /// A base URI to use if is relative. + /// A base URI to use if is relative. /// /// True if the asset could be found; otherwise false. public bool Exists(Uri uri, Uri baseUri = null) @@ -62,34 +56,31 @@ namespace Avalonia.Shared.PlatformSupport return GetAsset(uri, baseUri) != null; } - /// /// /// Opens the asset with the requested URI. /// /// The URI. /// - /// A base URI to use if is relative. + /// A base URI to use if is relative. /// /// A stream containing the asset contents. - /// + /// /// The asset could not be found. /// - public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).stream; + public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).Item1; - - /// /// /// Opens the asset with the requested URI and returns the asset stream and the /// assembly containing the asset. /// /// The URI. /// - /// A base URI to use if is relative. + /// A base URI to use if is relative. /// /// - /// The stream containing the asset contents together with the assembly. + /// The stream containing the resource contents together with the assembly. /// - /// + /// /// The asset could not be found. /// public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null) @@ -98,25 +89,22 @@ namespace Avalonia.Shared.PlatformSupport if (asset == null) { - throw new FileNotFoundException($"The asset {uri} could not be found."); + throw new FileNotFoundException($"The resource {uri} could not be found."); } return (asset.GetStream(), asset.Assembly); } - /// /// - /// Gets all assets at a specific location. + /// Gets all assets of a folder and subfolders that match specified uri. /// - /// The location of assets. - /// A tuple containing the absolute path to the resource and the owner assembly - public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location) + /// The URI. + /// All matching assets as a tuple of the absolute path to the asset and the assembly containing the asset + public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri uri) { - var assembly = GetAssembly(location); - - var availableAssets = assembly?.Assets; + var assembly = GetAssembly(uri); - return assembly?.Assets.Where(x => x.Key.Contains(location.AbsolutePath)) + return assembly?.Resources.Where(x => x.Key.Contains(uri.AbsolutePath)) .Select(x => (x.Key, x.Value.Assembly)) ?? Enumerable.Empty<(string AbsolutePath, Assembly Assembly)>(); } @@ -131,13 +119,13 @@ namespace Avalonia.Shared.PlatformSupport { throw new ArgumentException( "No default assembly, entry assembly or explicit assembly specified; " + - "don't know where to look up for the asset, try specifiyng assembly explicitly."); + "don't know where to look up for the resource, try specifiyng assembly explicitly."); } IAssetDescriptor rv; - var assetKey = uri.AbsolutePath; - asm.Assets.TryGetValue(assetKey, out rv); + var resourceKey = uri.AbsolutePath; + asm.Resources.TryGetValue(resourceKey, out rv); return rv; } throw new ArgumentException($"Invalid uri, see https://github.com/AvaloniaUI/Avalonia/issues/282#issuecomment-166982104", nameof(uri)); @@ -148,8 +136,9 @@ namespace Avalonia.Shared.PlatformSupport if (uri != null) { var qs = ParseQueryString(uri); + string assemblyName; - if (qs.TryGetValue("assembly", out var assemblyName)) + if (qs.TryGetValue("assembly", out assemblyName)) { return GetAssembly(assemblyName); } @@ -165,7 +154,8 @@ namespace Avalonia.Shared.PlatformSupport return _defaultAssembly; } - if (!AssemblyNameCache.TryGetValue(name, out var rv)) + AssemblyDescriptor rv; + if (!AssemblyNameCache.TryGetValue(name, out rv)) { var loadedAssemblies = AvaloniaLocator.Current.GetService().GetLoadedAssemblies(); var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name); @@ -232,15 +222,15 @@ namespace Avalonia.Shared.PlatformSupport if (assembly != null) { - Assets = assembly.GetManifestResourceNames() + Resources = assembly.GetManifestResourceNames() .ToDictionary(n => n, n => (IAssetDescriptor)new AssemblyResourceDescriptor(assembly, n)); Name = assembly.GetName().Name; } } public Assembly Assembly { get; } - public Dictionary Assets { get; } + public Dictionary Resources { get; } public string Name { get; } } } -} +} \ No newline at end of file diff --git a/tests/Avalonia.UnitTests/MockAssetLoader.cs b/tests/Avalonia.UnitTests/MockAssetLoader.cs index abfac77a5e..11d66128a7 100644 --- a/tests/Avalonia.UnitTests/MockAssetLoader.cs +++ b/tests/Avalonia.UnitTests/MockAssetLoader.cs @@ -32,9 +32,9 @@ namespace Avalonia.UnitTests return (Open(uri, baseUri), (Assembly)null); } - public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri location) + public IEnumerable<(string absolutePath, Assembly assembly)> GetAssets(Uri uri) { - return _assets.Keys.Where(x => x.AbsolutePath.Contains(location.AbsolutePath)) + return _assets.Keys.Where(x => x.AbsolutePath.Contains(uri.AbsolutePath)) .Select(x => (x.AbsolutePath, Assembly.GetEntryAssembly())); }