Nikita Tsukanov 10 年之前
父节点
当前提交
81f1bf51a8

+ 2 - 2
src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs

@@ -108,8 +108,8 @@ namespace Perspex.Markup.Xaml
         {
             var asm = type.GetTypeInfo().Assembly.GetName().Name;
             var typeName = type.FullName;
-            yield return new Uri("resource://application/" + asm + "/" + typeName + ".xaml");
-            yield return new Uri("resource://application/" + asm + "/" + typeName + ".paml");
+            yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm);
+            yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm);
 
         }
     }

+ 28 - 28
src/Perspex.Themes.Default/DefaultTheme.paml

@@ -1,30 +1,30 @@
 <Styles xmlns="https://github.com/perspex">
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.FocusAdorner.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.Button.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.Carousel.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.CheckBox.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ContentControl.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.DropDown.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.GridSplitter.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ItemsControl.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ListBox.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ListBoxItem.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.Menu.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.MenuItem.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.PopupRoot.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ProgressBar.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.RadioButton.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.Separator.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ScrollBar.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ScrollViewer.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.TabControl.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.TabStrip.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.TabStripItem.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.TextBox.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ToggleButton.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.Expander.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.ToolTip.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.TreeView.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.TreeViewItem.paml"/>
-  <StyleInclude Source="resource://application/Perspex.Themes.Default/Perspex.Themes.Default.Window.paml"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.FocusAdorner.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.Button.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.Carousel.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.CheckBox.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ContentControl.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.DropDown.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.GridSplitter.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ItemsControl.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ListBox.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ListBoxItem.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.Menu.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.MenuItem.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.PopupRoot.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ProgressBar.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.RadioButton.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.Separator.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ScrollBar.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ScrollViewer.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.TabControl.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.TabStrip.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.TabStripItem.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.TextBox.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ToggleButton.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.Expander.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.ToolTip.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.TreeView.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.TreeViewItem.paml?assembly=Perspex.Themes.Default"/>
+  <StyleInclude Source="resm:Perspex.Themes.Default.Window.paml?assembly=Perspex.Themes.Default"/>
 </Styles>

+ 79 - 24
src/Shared/PlatformSupport/AssetLoader.cs

@@ -15,26 +15,93 @@ namespace Perspex.Shared.PlatformSupport
     /// </summary>
     public class AssetLoader : IAssetLoader
     {
-        private static readonly Dictionary<string, Assembly> AssemblyNameCache
-            = new Dictionary<string, Assembly>();
+        class AssemblyDescriptor
+        {
+            public AssemblyDescriptor(Assembly assembly)
+            {
+                Assembly = assembly;
+                Resources = assembly.GetManifestResourceNames()
+                    .ToDictionary(n => n, n => (IAssetDescriptor)new AssemblyResourceDescriptor(assembly, n));
+                Name = assembly.GetName().Name;
+            }
+
+            public Assembly Assembly { get; }
+            public Dictionary<string, IAssetDescriptor> Resources { get; }
+            public string Name { get; }
+        }
+
 
-        private readonly Assembly _defaultAssembly;
+        private static readonly Dictionary<string, AssemblyDescriptor> AssemblyNameCache
+            = new Dictionary<string, AssemblyDescriptor>();
+
+        private readonly AssemblyDescriptor _defaultAssembly;
 
         public AssetLoader(Assembly assembly = null)
         {
-            _defaultAssembly = assembly;
+            if (assembly == null)
+                assembly = Assembly.GetEntryAssembly();
+            _defaultAssembly = new AssemblyDescriptor(assembly);
         }
+    
+
 
-        static Assembly GetAssembly(string name)
+        AssemblyDescriptor GetAssembly(string name)
         {
-            Assembly rv;
+            if (name == null)
+                return _defaultAssembly;
+            AssemblyDescriptor rv;
             if (!AssemblyNameCache.TryGetValue(name, out rv))
                 AssemblyNameCache[name] = rv =
-                    AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == name)
-                    ?? Assembly.Load(name);
+                    new AssemblyDescriptor(AppDomain.CurrentDomain.GetAssemblies()
+                        .FirstOrDefault(a => a.GetName().Name == name)
+                                           ?? Assembly.Load(name));
             return rv;
         }
 
+        interface IAssetDescriptor
+        {
+            Stream GetStream();
+        }
+
+
+        class AssemblyResourceDescriptor : IAssetDescriptor
+        {
+            private readonly Assembly _asm;
+            private readonly string _name;
+
+            public AssemblyResourceDescriptor(Assembly asm, string name)
+            {
+                _asm = asm;
+                _name = name;
+            }
+
+            public Stream GetStream()
+            {
+                return _asm.GetManifestResourceStream(_name);
+            }
+        }
+        
+
+        IAssetDescriptor GetAsset(Uri uri)
+        {
+            if (!uri.IsAbsoluteUri || uri.Scheme == "resm")
+            {
+                var qs = uri.Query.TrimStart('?')
+                    .Split('&')
+                    .Select(p => p.Split('='))
+                    .ToDictionary(p => p[0], p => p[1]);
+                //TODO: Replace _defaultAssembly by current one (need support from OmniXAML)
+                var asm = _defaultAssembly;
+                if (qs.ContainsKey("assembly"))
+                    asm = GetAssembly(qs["assembly"]);
+
+                IAssetDescriptor rv;
+                asm.Resources.TryGetValue(uri.AbsolutePath, out rv);
+                return rv;
+            }
+            throw new ArgumentException($"Invalid uri, see https://github.com/Perspex/Perspex/issues/282#issuecomment-166982104", nameof(uri));
+        }
+
         /// <summary>
         /// Checks if an asset with the specified URI exists.
         /// </summary>
@@ -42,11 +109,7 @@ namespace Perspex.Shared.PlatformSupport
         /// <returns>True if the asset could be found; otherwise false.</returns>
         public bool Exists(Uri uri)
         {
-            var parts = uri.AbsolutePath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
-            var asm = parts.Length == 1 ? (_defaultAssembly ?? Assembly.GetEntryAssembly()) : GetAssembly(parts[0]);
-            var typeName = parts[parts.Length == 1 ? 0 : 1];
-            var rv = asm.GetManifestResourceStream(typeName);
-            return rv != null;
+            return GetAsset(uri) != null;
         }
 
         /// <summary>
@@ -59,18 +122,10 @@ namespace Perspex.Shared.PlatformSupport
         /// </exception>
         public Stream Open(Uri uri)
         {
-            var parts = uri.AbsolutePath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
-            var asm = parts.Length == 1 ? (_defaultAssembly ?? Assembly.GetEntryAssembly()) : GetAssembly(parts[0]);
-            var typeName = parts[parts.Length == 1 ? 0 : 1];
-            var rv = asm.GetManifestResourceStream(typeName);
-            if (rv == null)
-            {
-#if DEBUG
-                var names = asm.GetManifestResourceNames().ToList();
-#endif
+            var asset = GetAsset(uri);
+            if (asset == null)
                 throw new FileNotFoundException($"The resource {uri} could not be found.");
-            }
-            return rv;
+            return asset.GetStream();
         }
     }
 }