From 9c3f6bfc74e470147f4bbb6302ba186cb06ce98a Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Sun, 6 Jun 2010 21:36:06 -0700 Subject: [PATCH] Tweak dynamic extension loader * Add "Assembly Src" directive to WebForms files loaded from vpp * Notify the OrchardHost when the .csproj file a a dynamic module is changed. * Make the registration of custom virtual path provider a bit more extensible, so that the custom VPP can be instantiated using DI. --HG-- branch : dev --- src/Orchard.Web/Global.asax.cs | 1 - src/Orchard/Environment/DefaultOrchardHost.cs | 6 +- .../Compilers/CSharpExtensionBuildProvider.cs | 7 +- .../Extensions/IExtensionManagerEvents.cs | 7 + .../Loaders/DynamicExtensionLoader.cs | 2 +- .../Loaders/MergedReadOnlyStreams.cs | 125 ++++++++++++++++++ .../Loaders/PrecompiledExtensionLoader.cs | 2 +- .../Loaders/WebFormsExtensionsVirtualFile.cs | 49 ++++--- .../WebFormsExtensionsVirtualPathProvider.cs | 38 +++--- .../Environment/ICustomVirtualPathProvider.cs | 7 + src/Orchard/Environment/OrchardStarter.cs | 11 ++ .../Dependencies/IDependenciesFolder.cs | 110 +++++++++++---- src/Orchard/Orchard.Framework.csproj | 3 + 13 files changed, 297 insertions(+), 71 deletions(-) create mode 100644 src/Orchard/Environment/Extensions/IExtensionManagerEvents.cs create mode 100644 src/Orchard/Environment/Extensions/Loaders/MergedReadOnlyStreams.cs create mode 100644 src/Orchard/Environment/ICustomVirtualPathProvider.cs diff --git a/src/Orchard.Web/Global.asax.cs b/src/Orchard.Web/Global.asax.cs index 066d1fe13..446724c5f 100644 --- a/src/Orchard.Web/Global.asax.cs +++ b/src/Orchard.Web/Global.asax.cs @@ -31,7 +31,6 @@ namespace Orchard.Web { RegisterRoutes(RouteTable.Routes); - HostingEnvironment.RegisterVirtualPathProvider(new WebFormsExtensionsVirtualPathProvider()); _host = OrchardStarter.CreateHost(MvcSingletons); _host.Initialize(); diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs index 8f3b29b89..353556d61 100644 --- a/src/Orchard/Environment/DefaultOrchardHost.cs +++ b/src/Orchard/Environment/DefaultOrchardHost.cs @@ -17,7 +17,7 @@ using Orchard.Mvc.ViewEngines; using Orchard.Utility.Extensions; namespace Orchard.Environment { - public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler { + public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler, IExtensionManagerEvents { private readonly ControllerBuilder _controllerBuilder; private readonly IShellSettingsManager _shellSettingsManager; @@ -147,5 +147,9 @@ namespace Orchard.Environment { void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor) { _current = null; } + + void IExtensionManagerEvents.ModuleChanged(string moduleName) { + _current = null; + } } } diff --git a/src/Orchard/Environment/Extensions/Compilers/CSharpExtensionBuildProvider.cs b/src/Orchard/Environment/Extensions/Compilers/CSharpExtensionBuildProvider.cs index 826eccc64..8e4e3bd9e 100644 --- a/src/Orchard/Environment/Extensions/Compilers/CSharpExtensionBuildProvider.cs +++ b/src/Orchard/Environment/Extensions/Compilers/CSharpExtensionBuildProvider.cs @@ -1,4 +1,5 @@ -using System.Web.Compilation; +using System.Diagnostics; +using System.Web.Compilation; namespace Orchard.Environment.Extensions.Compilers { public class CSharpExtensionBuildProvider : BuildProvider { @@ -11,6 +12,10 @@ namespace Orchard.Environment.Extensions.Compilers { public override CompilerType CodeCompilerType { get { return _codeCompilerType; } } public override void GenerateCode(AssemblyBuilder assemblyBuilder) { + //Debug.WriteLine(string.Format("BuildProvider for file \"{0}\"", this.VirtualPath)); + + //TODO: It probably would be better to access the OrchardHost container + // to resolve these dependencies. var virtualPathProvider = new DefaultVirtualPathProvider(); var compiler = new CSharpProjectMediumTrustCompiler(virtualPathProvider); diff --git a/src/Orchard/Environment/Extensions/IExtensionManagerEvents.cs b/src/Orchard/Environment/Extensions/IExtensionManagerEvents.cs new file mode 100644 index 000000000..c7be80e9f --- /dev/null +++ b/src/Orchard/Environment/Extensions/IExtensionManagerEvents.cs @@ -0,0 +1,7 @@ +using Orchard.Events; + +namespace Orchard.Environment.Extensions { + public interface IExtensionManagerEvents : IEventHandler { + void ModuleChanged(string moduleName); + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/Extensions/Loaders/DynamicExtensionLoader.cs b/src/Orchard/Environment/Extensions/Loaders/DynamicExtensionLoader.cs index fd000783c..e00dffd40 100644 --- a/src/Orchard/Environment/Extensions/Loaders/DynamicExtensionLoader.cs +++ b/src/Orchard/Environment/Extensions/Loaders/DynamicExtensionLoader.cs @@ -28,7 +28,7 @@ namespace Orchard.Environment.Extensions.Loaders { var assembly = _buildManager.GetCompiledAssembly(projectPath); if (_hostEnvironment.IsFullTrust) { - _dependenciesFolder.StoreAssemblyFile(descriptor.Name, assembly.Location); + _dependenciesFolder.StoreBuildProviderAssembly(descriptor.Name, projectPath, assembly); } return new ExtensionEntry { diff --git a/src/Orchard/Environment/Extensions/Loaders/MergedReadOnlyStreams.cs b/src/Orchard/Environment/Extensions/Loaders/MergedReadOnlyStreams.cs new file mode 100644 index 000000000..fd3ecea96 --- /dev/null +++ b/src/Orchard/Environment/Extensions/Loaders/MergedReadOnlyStreams.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Orchard.Environment.Extensions.Loaders { + /// + /// Expose a read-only stream as the concatenation of a list of read-only streams + /// + public class MergedReadOnlyStreams : Stream { + private class StreamDescriptor { + public int Index { get; set; } + public Stream Stream { get; set; } + public long Offset { get; set; } + public long Length { get; set; } + public long Limit { get { return Offset + Length; } } + } + + private readonly List _streams; + private long _position; + + public MergedReadOnlyStreams(params Stream[] streams) { + _streams = CreateDescritors(streams).ToList(); + } + + private static IEnumerable CreateDescritors(params Stream[] streams) { + long offset = 0; + int index = 0; + foreach (var stream in streams) { + yield return new StreamDescriptor { + Stream = stream, + Index = index, + Length = stream.Length, + Offset = offset + }; + + offset += stream.Length; + index++; + } + } + public override void Flush() { + } + + public override long Seek(long offset, SeekOrigin origin) { + switch (origin) { + case SeekOrigin.Begin: + _position = offset; + break; + case SeekOrigin.Current: + _position += offset; + break; + case SeekOrigin.End: + _position = Length + offset; + break; + default: + throw new ArgumentOutOfRangeException("origin"); + } + return _position; + } + + public override void SetLength(long value) { + } + + public override int Read(byte[] buffer, int offset, int count) { + int totalRead = 0; + while (count > 0) { + // Find stream for current position (might fail if end of all streams) + var descriptor = GetDescriptor(_position); + if (descriptor == null) + break; + + // Read bytes from the current stream + int read = descriptor.Stream.Read(buffer, offset, count); + if (read == 0) + break; + + _position += read; + totalRead += read; + count -= read; + offset += read; + } + return totalRead; + } + + private StreamDescriptor GetDescriptor(long position) { + return _streams.SingleOrDefault(stream => stream.Offset <= position && position < stream.Limit); + } + + public override void Write(byte[] buffer, int offset, int count) { + } + + public override bool CanRead { + get { return true; } + } + + public override bool CanSeek { + get { return _streams.All(d => d.Stream.CanSeek); } + } + + public override bool CanWrite { + get { return false; } + } + + public override long Length { + get { return _streams.Aggregate(0L, (prev, desc) => prev + desc.Length); } + } + + public override long Position { + get { return _position; } + set { + if (!CanSeek) + throw new InvalidOperationException(); + + _position = Position; + + // Update the position of all streams + foreach(var desc in _streams) { + if (_position < desc.Offset) desc.Stream.Position = 0; + else if (_position > desc.Limit) desc.Stream.Position = desc.Stream.Length; + else desc.Stream.Position = _position - desc.Offset; + } + } + } + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/Extensions/Loaders/PrecompiledExtensionLoader.cs b/src/Orchard/Environment/Extensions/Loaders/PrecompiledExtensionLoader.cs index 8e65e2183..1583b27fd 100644 --- a/src/Orchard/Environment/Extensions/Loaders/PrecompiledExtensionLoader.cs +++ b/src/Orchard/Environment/Extensions/Loaders/PrecompiledExtensionLoader.cs @@ -23,7 +23,7 @@ namespace Orchard.Environment.Extensions.Loaders { if (!_virtualPathProvider.FileExists(extensionPath)) return null; - _folder.StoreAssemblyFile(descriptor.Name, _virtualPathProvider.MapPath(extensionPath)); + _folder.StorePrecompiledAssembly(descriptor.Name, extensionPath); var assembly = _folder.LoadAssembly(descriptor.Name); if (assembly == null) diff --git a/src/Orchard/Environment/Extensions/Loaders/WebFormsExtensionsVirtualFile.cs b/src/Orchard/Environment/Extensions/Loaders/WebFormsExtensionsVirtualFile.cs index 11ef6a4c6..649c88c61 100644 --- a/src/Orchard/Environment/Extensions/Loaders/WebFormsExtensionsVirtualFile.cs +++ b/src/Orchard/Environment/Extensions/Loaders/WebFormsExtensionsVirtualFile.cs @@ -1,15 +1,15 @@ using System.IO; -using System.Reflection; using System.Web.Hosting; +using Orchard.FileSystems.Dependencies; namespace Orchard.Environment.Extensions.Loaders { public class WebFormsExtensionsVirtualFile : VirtualFile { - private readonly Assembly _assembly; + private readonly DependencyDescriptor _dependencyDescriptor; private readonly VirtualFile _actualFile; - public WebFormsExtensionsVirtualFile(string virtualPath, Assembly assembly, VirtualFile actualFile) + public WebFormsExtensionsVirtualFile(string virtualPath, DependencyDescriptor dependencyDescriptor, VirtualFile actualFile) : base(virtualPath) { - _assembly = assembly; + _dependencyDescriptor = dependencyDescriptor; _actualFile = actualFile; } @@ -26,26 +26,37 @@ namespace Orchard.Environment.Extensions.Loaders { } public override Stream Open() { - var reader = new StreamReader(_actualFile.Open()); - var memoryStream = new MemoryStream(); - int length; - using (var writer = new StreamWriter(memoryStream)) { + using (var actualStream = _actualFile.Open()) { + var reader = new StreamReader(actualStream); - bool assemblyDirectiveAdded = false; - for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { + var memoryStream = new MemoryStream(); + int length; + using (var writer = new StreamWriter(memoryStream)) { - if (!string.IsNullOrWhiteSpace(line) && !assemblyDirectiveAdded) { - line += string.Format("<%@ Assembly Name=\"{0}\"%>", _assembly); - assemblyDirectiveAdded = true; + bool assemblyDirectiveAdded = false; + for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { + + if (!string.IsNullOrWhiteSpace(line) && !assemblyDirectiveAdded) { + line += GetAssemblyDirective(); + assemblyDirectiveAdded = true; + } + + writer.WriteLine(line); } - - writer.WriteLine(line); + writer.Flush(); + length = (int) memoryStream.Length; } - writer.Flush(); - length = (int)memoryStream.Length; + return new MemoryStream(memoryStream.GetBuffer(), 0, length); + } + } + + private string GetAssemblyDirective() { + if (_dependencyDescriptor.IsFromBuildProvider) { + return string.Format("<%@ Assembly Src=\"{0}\"%>", _dependencyDescriptor.VirtualPath); + } + else { + return string.Format("<%@ Assembly Name=\"{0}\"%>", _dependencyDescriptor.ModuleName); } - var result = new MemoryStream(memoryStream.GetBuffer(), 0, length); - return result; } } } diff --git a/src/Orchard/Environment/Extensions/Loaders/WebFormsExtensionsVirtualPathProvider.cs b/src/Orchard/Environment/Extensions/Loaders/WebFormsExtensionsVirtualPathProvider.cs index 39a81f0d0..e7c294df5 100644 --- a/src/Orchard/Environment/Extensions/Loaders/WebFormsExtensionsVirtualPathProvider.cs +++ b/src/Orchard/Environment/Extensions/Loaders/WebFormsExtensionsVirtualPathProvider.cs @@ -4,17 +4,13 @@ using System.Web.Hosting; using Orchard.FileSystems.Dependencies; namespace Orchard.Environment.Extensions.Loaders { - public class WebFormsExtensionsVirtualPathProvider : VirtualPathProvider { - private IDependenciesFolder _dependenciesFolder; - private const string _prefix1 = "~/Modules/"; - private const string _prefix2 = "/Modules/"; + public class WebFormsExtensionsVirtualPathProvider : VirtualPathProvider, ICustomVirtualPathProvider { + private readonly IDependenciesFolder _dependenciesFolder; + private readonly string[] _prefixes = { "~/Modules/", "/Modules/" }; + private readonly string[] _extensions = { ".ascx", ".aspx", ".master" }; - public WebFormsExtensionsVirtualPathProvider() { - } - - protected override void Initialize() { - base.Initialize(); - _dependenciesFolder = new DefaultDependenciesFolder(new DefaultVirtualPathProvider()); + public WebFormsExtensionsVirtualPathProvider(IDependenciesFolder dependenciesFolder) { + _dependenciesFolder = dependenciesFolder; } public override bool DirectoryExists(string virtualDir) { @@ -28,11 +24,11 @@ namespace Orchard.Environment.Extensions.Loaders { public override VirtualFile GetFile(string virtualPath) { var actualFile = Previous.GetFile(virtualPath); - var prefix = PrefixMatch(virtualPath); + var prefix = PrefixMatch(virtualPath, _prefixes); if (prefix == null) return actualFile; - var extension = ExtensionMatch(virtualPath, ".ascx", ".aspx", ".master"); + var extension = ExtensionMatch(virtualPath, _extensions); if (extension == null) return actualFile; @@ -42,13 +38,13 @@ namespace Orchard.Environment.Extensions.Loaders { // It looks like we have a module name. Is this one of this modules // with its assembly stored in the "App_Data/Dependencies" folder? - var assembly = _dependenciesFolder.LoadAssembly(moduleName); - if (assembly == null) + var dependencyDescriptor = _dependenciesFolder.GetDescriptor(moduleName); + if (dependencyDescriptor == null) return actualFile; // Yes: we need to wrap the VirtualFile to add the <%@ Assembly Name=".."%> directive // in the content. - return new WebFormsExtensionsVirtualFile(virtualPath, assembly, actualFile); + return new WebFormsExtensionsVirtualFile(virtualPath, dependencyDescriptor, actualFile); } private string ModuleMatch(string virtualPath, string prefix) { @@ -65,13 +61,13 @@ namespace Orchard.Environment.Extensions.Loaders { .FirstOrDefault(e => virtualPath.EndsWith(e, StringComparison.OrdinalIgnoreCase)); } - private string PrefixMatch(string virtualPath) { - if (virtualPath.StartsWith(_prefix1)) - return _prefix1; - if (virtualPath.StartsWith(_prefix2)) - return _prefix2; - return null; + private string PrefixMatch(string virtualPath, params string[] prefixes) { + return prefixes + .FirstOrDefault(p => virtualPath.StartsWith(p, StringComparison.OrdinalIgnoreCase)); + } + VirtualPathProvider ICustomVirtualPathProvider.Instance { + get { return this; } } } } \ No newline at end of file diff --git a/src/Orchard/Environment/ICustomVirtualPathProvider.cs b/src/Orchard/Environment/ICustomVirtualPathProvider.cs new file mode 100644 index 000000000..47217baee --- /dev/null +++ b/src/Orchard/Environment/ICustomVirtualPathProvider.cs @@ -0,0 +1,7 @@ +using System.Web.Hosting; + +namespace Orchard.Environment { + public interface ICustomVirtualPathProvider { + VirtualPathProvider Instance { get; } + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs index a86204858..5115c53cb 100644 --- a/src/Orchard/Environment/OrchardStarter.cs +++ b/src/Orchard/Environment/OrchardStarter.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Configuration; using System.IO; using System.Web.Hosting; @@ -33,6 +34,7 @@ namespace Orchard.Environment { builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); RegisterVolatileProvider(builder); RegisterVolatileProvider(builder); @@ -117,6 +119,15 @@ namespace Orchard.Environment { public static IOrchardHost CreateHost(Action registrations) { var container = CreateHostContainer(registrations); + + // + // Register Virtual Path Providers + // + foreach (var vpp in container.Resolve>()) { + HostingEnvironment.RegisterVirtualPathProvider(vpp.Instance); + } + + return container.Resolve(); } } diff --git a/src/Orchard/FileSystems/Dependencies/IDependenciesFolder.cs b/src/Orchard/FileSystems/Dependencies/IDependenciesFolder.cs index 291da06a9..321f74e16 100644 --- a/src/Orchard/FileSystems/Dependencies/IDependenciesFolder.cs +++ b/src/Orchard/FileSystems/Dependencies/IDependenciesFolder.cs @@ -1,23 +1,40 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Web.Caching; +using System.Web.Hosting; using System.Xml.Linq; using Orchard.Caching; using Orchard.Environment; +using Orchard.Environment.Extensions; +using Orchard.Environment.Topology; namespace Orchard.FileSystems.Dependencies { + public class DependencyDescriptor { + public string ModuleName { get; set; } + public bool IsFromBuildProvider { get; set; } + public string VirtualPath { get; set; } + public string FileName { get; set; } + } + public interface IDependenciesFolder : IVolatileProvider { - void StoreAssemblyFile(string assemblyName, string assemblyFileName); + void StoreBuildProviderAssembly(string moduleName, string virtualPath, Assembly assembly); + void StorePrecompiledAssembly(string moduleName, string virtualPath); + DependencyDescriptor GetDescriptor(string moduleName); Assembly LoadAssembly(string assemblyName); } public class DefaultDependenciesFolder : IDependenciesFolder { + private readonly string _prefix = Guid.NewGuid().ToString("n"); private const string _basePath = "~/App_Data/Dependencies"; private readonly IVirtualPathProvider _virtualPathProvider; + private readonly IExtensionManagerEvents _events; - public DefaultDependenciesFolder(IVirtualPathProvider virtualPathProvider) { + public DefaultDependenciesFolder(IVirtualPathProvider virtualPathProvider, IExtensionManagerEvents events) { _virtualPathProvider = virtualPathProvider; + _events = events; } private string BasePath { @@ -32,21 +49,60 @@ namespace Orchard.FileSystems.Dependencies { } } - public void StoreAssemblyFile(string assemblyName, string assemblyFileName) { + public void StoreBuildProviderAssembly(string moduleName, string virtualPath, Assembly assembly) { + _virtualPathProvider.CreateDirectory(BasePath); + + var descriptor = new DependencyDescriptor { + ModuleName = moduleName, + IsFromBuildProvider = true, + VirtualPath = virtualPath, + FileName = assembly.Location + }; + + StoreDepencyInformation(descriptor); + +#if true + var cacheDependency = HostingEnvironment.VirtualPathProvider.GetCacheDependency( + virtualPath, + new[] { virtualPath }, + DateTime.UtcNow); + + HostingEnvironment.Cache.Add( + _prefix + virtualPath, + moduleName, + cacheDependency, + Cache.NoAbsoluteExpiration, + Cache.NoSlidingExpiration, + CacheItemPriority.NotRemovable, + (key, value, reason) => _events.ModuleChanged((string) value)); +#endif + } + + public void StorePrecompiledAssembly(string moduleName, string virtualPath) { _virtualPathProvider.CreateDirectory(BasePath); // Only store assembly if it's more recent that what we have stored already (if anything) - if (IsNewerAssembly(assemblyName, assemblyFileName)) { + var assemblyFileName = _virtualPathProvider.MapPath(virtualPath); + if (IsNewerAssembly(moduleName, assemblyFileName)) { var destinationFileName = Path.GetFileName(assemblyFileName); var destinationPath = _virtualPathProvider.MapPath(_virtualPathProvider.Combine(BasePath, destinationFileName)); File.Copy(assemblyFileName, destinationPath, true); - StoreDepencyInformation(assemblyName, destinationFileName); + StoreDepencyInformation(new DependencyDescriptor { + ModuleName = moduleName, + IsFromBuildProvider = false, + VirtualPath = virtualPath, + FileName = destinationFileName + }); } } - private bool IsNewerAssembly(string assemblyName, string assemblyFileName) { - var dependency = ReadDependencies().SingleOrDefault(d => d.Name == assemblyName); + public DependencyDescriptor GetDescriptor(string moduleName) { + return ReadDependencies().SingleOrDefault(d => d.ModuleName == moduleName); + } + + private bool IsNewerAssembly(string moduleName, string assemblyFileName) { + var dependency = ReadDependencies().SingleOrDefault(d => d.ModuleName == moduleName); if (dependency == null) { return true; } @@ -59,15 +115,15 @@ namespace Orchard.FileSystems.Dependencies { return (File.GetLastWriteTimeUtc(existingFileName) < File.GetLastWriteTimeUtc(assemblyFileName)); } - private void StoreDepencyInformation(string name, string fileName) { + private void StoreDepencyInformation(DependencyDescriptor descriptor) { var dependencies = ReadDependencies().ToList(); - - var dependency = dependencies.SingleOrDefault(d => d.Name == name); - if (dependency == null) { - dependency = new DependencyDescritpor { Name = name, FileName = fileName }; - dependencies.Add(dependency); + int index = dependencies.FindIndex(d => d.ModuleName == descriptor.ModuleName); + if (index < 0) { + dependencies.Add(descriptor); + } + else { + dependencies[index] = descriptor; } - dependency.FileName = fileName; WriteDependencies(dependencies); } @@ -75,7 +131,7 @@ namespace Orchard.FileSystems.Dependencies { public Assembly LoadAssembly(string assemblyName) { _virtualPathProvider.CreateDirectory(BasePath); - var dependency = ReadDependencies().SingleOrDefault(d => d.Name == assemblyName); + var dependency = ReadDependencies().SingleOrDefault(d => d.ModuleName == assemblyName); if (dependency == null) return null; @@ -85,30 +141,32 @@ namespace Orchard.FileSystems.Dependencies { return Assembly.Load(Path.GetFileNameWithoutExtension(dependency.FileName)); } - private class DependencyDescritpor { - public string Name { get; set; } - public string FileName { get; set; } - } - - private IEnumerable ReadDependencies() { + private IEnumerable ReadDependencies() { if (!_virtualPathProvider.FileExists(PersistencePath)) - return Enumerable.Empty(); + return Enumerable.Empty(); using (var stream = _virtualPathProvider.OpenFile(PersistencePath)) { XDocument document = XDocument.Load(stream); return document .Elements(ns("Dependencies")) .Elements(ns("Dependency")) - .Select(e => new DependencyDescritpor { Name = e.Element("Name").Value, FileName = e.Element("FileName").Value }) + .Select(e => new DependencyDescriptor { + ModuleName = e.Element("ModuleName").Value, + VirtualPath = e.Element("VirtualPath").Value, + FileName = e.Element("FileName").Value, + IsFromBuildProvider = bool.Parse(e.Element("IsFromBuildProvider").Value) + }) .ToList(); } } - private void WriteDependencies(IEnumerable dependencies) { + private void WriteDependencies(IEnumerable dependencies) { var document = new XDocument(); document.Add(new XElement(ns("Dependencies"))); var elements = dependencies.Select(d => new XElement("Dependency", - new XElement(ns("Name"), d.Name), + new XElement(ns("ModuleName"), d.ModuleName), + new XElement(ns("VirtualPath"), d.VirtualPath), + new XElement(ns("IsFromBuildProvider"), d.IsFromBuildProvider), new XElement(ns("FileName"), d.FileName))); document.Root.Add(elements); diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 1a902fbdc..75bce73ff 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -341,8 +341,11 @@ + + +