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
This commit is contained in:
Renaud Paquay
2010-06-06 21:36:06 -07:00
parent 2c9d0caf0a
commit 9c3f6bfc74
13 changed files with 297 additions and 71 deletions

View File

@@ -31,7 +31,6 @@ namespace Orchard.Web {
RegisterRoutes(RouteTable.Routes); RegisterRoutes(RouteTable.Routes);
HostingEnvironment.RegisterVirtualPathProvider(new WebFormsExtensionsVirtualPathProvider());
_host = OrchardStarter.CreateHost(MvcSingletons); _host = OrchardStarter.CreateHost(MvcSingletons);
_host.Initialize(); _host.Initialize();

View File

@@ -17,7 +17,7 @@ using Orchard.Mvc.ViewEngines;
using Orchard.Utility.Extensions; using Orchard.Utility.Extensions;
namespace Orchard.Environment { namespace Orchard.Environment {
public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler { public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler, IExtensionManagerEvents {
private readonly ControllerBuilder _controllerBuilder; private readonly ControllerBuilder _controllerBuilder;
private readonly IShellSettingsManager _shellSettingsManager; private readonly IShellSettingsManager _shellSettingsManager;
@@ -147,5 +147,9 @@ namespace Orchard.Environment {
void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor) { void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor) {
_current = null; _current = null;
} }
void IExtensionManagerEvents.ModuleChanged(string moduleName) {
_current = null;
}
} }
} }

View File

@@ -1,4 +1,5 @@
using System.Web.Compilation; using System.Diagnostics;
using System.Web.Compilation;
namespace Orchard.Environment.Extensions.Compilers { namespace Orchard.Environment.Extensions.Compilers {
public class CSharpExtensionBuildProvider : BuildProvider { public class CSharpExtensionBuildProvider : BuildProvider {
@@ -11,6 +12,10 @@ namespace Orchard.Environment.Extensions.Compilers {
public override CompilerType CodeCompilerType { get { return _codeCompilerType; } } public override CompilerType CodeCompilerType { get { return _codeCompilerType; } }
public override void GenerateCode(AssemblyBuilder assemblyBuilder) { 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 virtualPathProvider = new DefaultVirtualPathProvider();
var compiler = new CSharpProjectMediumTrustCompiler(virtualPathProvider); var compiler = new CSharpProjectMediumTrustCompiler(virtualPathProvider);

View File

@@ -0,0 +1,7 @@
using Orchard.Events;
namespace Orchard.Environment.Extensions {
public interface IExtensionManagerEvents : IEventHandler {
void ModuleChanged(string moduleName);
}
}

View File

@@ -28,7 +28,7 @@ namespace Orchard.Environment.Extensions.Loaders {
var assembly = _buildManager.GetCompiledAssembly(projectPath); var assembly = _buildManager.GetCompiledAssembly(projectPath);
if (_hostEnvironment.IsFullTrust) { if (_hostEnvironment.IsFullTrust) {
_dependenciesFolder.StoreAssemblyFile(descriptor.Name, assembly.Location); _dependenciesFolder.StoreBuildProviderAssembly(descriptor.Name, projectPath, assembly);
} }
return new ExtensionEntry { return new ExtensionEntry {

View File

@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Orchard.Environment.Extensions.Loaders {
/// <summary>
/// Expose a read-only stream as the concatenation of a list of read-only streams
/// </summary>
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<StreamDescriptor> _streams;
private long _position;
public MergedReadOnlyStreams(params Stream[] streams) {
_streams = CreateDescritors(streams).ToList();
}
private static IEnumerable<StreamDescriptor> 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;
}
}
}
}
}

View File

@@ -23,7 +23,7 @@ namespace Orchard.Environment.Extensions.Loaders {
if (!_virtualPathProvider.FileExists(extensionPath)) if (!_virtualPathProvider.FileExists(extensionPath))
return null; return null;
_folder.StoreAssemblyFile(descriptor.Name, _virtualPathProvider.MapPath(extensionPath)); _folder.StorePrecompiledAssembly(descriptor.Name, extensionPath);
var assembly = _folder.LoadAssembly(descriptor.Name); var assembly = _folder.LoadAssembly(descriptor.Name);
if (assembly == null) if (assembly == null)

View File

@@ -1,15 +1,15 @@
using System.IO; using System.IO;
using System.Reflection;
using System.Web.Hosting; using System.Web.Hosting;
using Orchard.FileSystems.Dependencies;
namespace Orchard.Environment.Extensions.Loaders { namespace Orchard.Environment.Extensions.Loaders {
public class WebFormsExtensionsVirtualFile : VirtualFile { public class WebFormsExtensionsVirtualFile : VirtualFile {
private readonly Assembly _assembly; private readonly DependencyDescriptor _dependencyDescriptor;
private readonly VirtualFile _actualFile; private readonly VirtualFile _actualFile;
public WebFormsExtensionsVirtualFile(string virtualPath, Assembly assembly, VirtualFile actualFile) public WebFormsExtensionsVirtualFile(string virtualPath, DependencyDescriptor dependencyDescriptor, VirtualFile actualFile)
: base(virtualPath) { : base(virtualPath) {
_assembly = assembly; _dependencyDescriptor = dependencyDescriptor;
_actualFile = actualFile; _actualFile = actualFile;
} }
@@ -26,7 +26,9 @@ namespace Orchard.Environment.Extensions.Loaders {
} }
public override Stream Open() { public override Stream Open() {
var reader = new StreamReader(_actualFile.Open()); using (var actualStream = _actualFile.Open()) {
var reader = new StreamReader(actualStream);
var memoryStream = new MemoryStream(); var memoryStream = new MemoryStream();
int length; int length;
using (var writer = new StreamWriter(memoryStream)) { using (var writer = new StreamWriter(memoryStream)) {
@@ -35,7 +37,7 @@ namespace Orchard.Environment.Extensions.Loaders {
for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) {
if (!string.IsNullOrWhiteSpace(line) && !assemblyDirectiveAdded) { if (!string.IsNullOrWhiteSpace(line) && !assemblyDirectiveAdded) {
line += string.Format("<%@ Assembly Name=\"{0}\"%>", _assembly); line += GetAssemblyDirective();
assemblyDirectiveAdded = true; assemblyDirectiveAdded = true;
} }
@@ -44,8 +46,17 @@ namespace Orchard.Environment.Extensions.Loaders {
writer.Flush(); writer.Flush();
length = (int) memoryStream.Length; length = (int) memoryStream.Length;
} }
var result = new MemoryStream(memoryStream.GetBuffer(), 0, length); return new MemoryStream(memoryStream.GetBuffer(), 0, length);
return result; }
}
private string GetAssemblyDirective() {
if (_dependencyDescriptor.IsFromBuildProvider) {
return string.Format("<%@ Assembly Src=\"{0}\"%>", _dependencyDescriptor.VirtualPath);
}
else {
return string.Format("<%@ Assembly Name=\"{0}\"%>", _dependencyDescriptor.ModuleName);
}
} }
} }
} }

View File

@@ -4,17 +4,13 @@ using System.Web.Hosting;
using Orchard.FileSystems.Dependencies; using Orchard.FileSystems.Dependencies;
namespace Orchard.Environment.Extensions.Loaders { namespace Orchard.Environment.Extensions.Loaders {
public class WebFormsExtensionsVirtualPathProvider : VirtualPathProvider { public class WebFormsExtensionsVirtualPathProvider : VirtualPathProvider, ICustomVirtualPathProvider {
private IDependenciesFolder _dependenciesFolder; private readonly IDependenciesFolder _dependenciesFolder;
private const string _prefix1 = "~/Modules/"; private readonly string[] _prefixes = { "~/Modules/", "/Modules/" };
private const string _prefix2 = "/Modules/"; private readonly string[] _extensions = { ".ascx", ".aspx", ".master" };
public WebFormsExtensionsVirtualPathProvider() { public WebFormsExtensionsVirtualPathProvider(IDependenciesFolder dependenciesFolder) {
} _dependenciesFolder = dependenciesFolder;
protected override void Initialize() {
base.Initialize();
_dependenciesFolder = new DefaultDependenciesFolder(new DefaultVirtualPathProvider());
} }
public override bool DirectoryExists(string virtualDir) { public override bool DirectoryExists(string virtualDir) {
@@ -28,11 +24,11 @@ namespace Orchard.Environment.Extensions.Loaders {
public override VirtualFile GetFile(string virtualPath) { public override VirtualFile GetFile(string virtualPath) {
var actualFile = Previous.GetFile(virtualPath); var actualFile = Previous.GetFile(virtualPath);
var prefix = PrefixMatch(virtualPath); var prefix = PrefixMatch(virtualPath, _prefixes);
if (prefix == null) if (prefix == null)
return actualFile; return actualFile;
var extension = ExtensionMatch(virtualPath, ".ascx", ".aspx", ".master"); var extension = ExtensionMatch(virtualPath, _extensions);
if (extension == null) if (extension == null)
return actualFile; 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 // It looks like we have a module name. Is this one of this modules
// with its assembly stored in the "App_Data/Dependencies" folder? // with its assembly stored in the "App_Data/Dependencies" folder?
var assembly = _dependenciesFolder.LoadAssembly(moduleName); var dependencyDescriptor = _dependenciesFolder.GetDescriptor(moduleName);
if (assembly == null) if (dependencyDescriptor == null)
return actualFile; return actualFile;
// Yes: we need to wrap the VirtualFile to add the <%@ Assembly Name=".."%> directive // Yes: we need to wrap the VirtualFile to add the <%@ Assembly Name=".."%> directive
// in the content. // in the content.
return new WebFormsExtensionsVirtualFile(virtualPath, assembly, actualFile); return new WebFormsExtensionsVirtualFile(virtualPath, dependencyDescriptor, actualFile);
} }
private string ModuleMatch(string virtualPath, string prefix) { private string ModuleMatch(string virtualPath, string prefix) {
@@ -65,13 +61,13 @@ namespace Orchard.Environment.Extensions.Loaders {
.FirstOrDefault(e => virtualPath.EndsWith(e, StringComparison.OrdinalIgnoreCase)); .FirstOrDefault(e => virtualPath.EndsWith(e, StringComparison.OrdinalIgnoreCase));
} }
private string PrefixMatch(string virtualPath) { private string PrefixMatch(string virtualPath, params string[] prefixes) {
if (virtualPath.StartsWith(_prefix1)) return prefixes
return _prefix1; .FirstOrDefault(p => virtualPath.StartsWith(p, StringComparison.OrdinalIgnoreCase));
if (virtualPath.StartsWith(_prefix2)) }
return _prefix2;
return null;
VirtualPathProvider ICustomVirtualPathProvider.Instance {
get { return this; }
} }
} }
} }

View File

@@ -0,0 +1,7 @@
using System.Web.Hosting;
namespace Orchard.Environment {
public interface ICustomVirtualPathProvider {
VirtualPathProvider Instance { get; }
}
}

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Configuration; using System.Configuration;
using System.IO; using System.IO;
using System.Web.Hosting; using System.Web.Hosting;
@@ -33,6 +34,7 @@ namespace Orchard.Environment {
builder.RegisterType<DefaultCacheHolder>().As<ICacheHolder>().SingleInstance(); builder.RegisterType<DefaultCacheHolder>().As<ICacheHolder>().SingleInstance();
builder.RegisterType<DefaultHostEnvironment>().As<IHostEnvironment>().SingleInstance(); builder.RegisterType<DefaultHostEnvironment>().As<IHostEnvironment>().SingleInstance();
builder.RegisterType<DefaultBuildManager>().As<IBuildManager>().SingleInstance(); builder.RegisterType<DefaultBuildManager>().As<IBuildManager>().SingleInstance();
builder.RegisterType<WebFormsExtensionsVirtualPathProvider>().As<ICustomVirtualPathProvider>().SingleInstance();
RegisterVolatileProvider<WebSiteFolder, IWebSiteFolder>(builder); RegisterVolatileProvider<WebSiteFolder, IWebSiteFolder>(builder);
RegisterVolatileProvider<AppDataFolder, IAppDataFolder>(builder); RegisterVolatileProvider<AppDataFolder, IAppDataFolder>(builder);
@@ -117,6 +119,15 @@ namespace Orchard.Environment {
public static IOrchardHost CreateHost(Action<ContainerBuilder> registrations) { public static IOrchardHost CreateHost(Action<ContainerBuilder> registrations) {
var container = CreateHostContainer(registrations); var container = CreateHostContainer(registrations);
//
// Register Virtual Path Providers
//
foreach (var vpp in container.Resolve<IEnumerable<ICustomVirtualPathProvider>>()) {
HostingEnvironment.RegisterVirtualPathProvider(vpp.Instance);
}
return container.Resolve<IOrchardHost>(); return container.Resolve<IOrchardHost>();
} }
} }

View File

@@ -1,23 +1,40 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Web.Caching;
using System.Web.Hosting;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.Caching; using Orchard.Caching;
using Orchard.Environment; using Orchard.Environment;
using Orchard.Environment.Extensions;
using Orchard.Environment.Topology;
namespace Orchard.FileSystems.Dependencies { 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 { 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); Assembly LoadAssembly(string assemblyName);
} }
public class DefaultDependenciesFolder : IDependenciesFolder { public class DefaultDependenciesFolder : IDependenciesFolder {
private readonly string _prefix = Guid.NewGuid().ToString("n");
private const string _basePath = "~/App_Data/Dependencies"; private const string _basePath = "~/App_Data/Dependencies";
private readonly IVirtualPathProvider _virtualPathProvider; private readonly IVirtualPathProvider _virtualPathProvider;
private readonly IExtensionManagerEvents _events;
public DefaultDependenciesFolder(IVirtualPathProvider virtualPathProvider) { public DefaultDependenciesFolder(IVirtualPathProvider virtualPathProvider, IExtensionManagerEvents events) {
_virtualPathProvider = virtualPathProvider; _virtualPathProvider = virtualPathProvider;
_events = events;
} }
private string BasePath { 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); _virtualPathProvider.CreateDirectory(BasePath);
// Only store assembly if it's more recent that what we have stored already (if anything) // 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 destinationFileName = Path.GetFileName(assemblyFileName);
var destinationPath = _virtualPathProvider.MapPath(_virtualPathProvider.Combine(BasePath, destinationFileName)); var destinationPath = _virtualPathProvider.MapPath(_virtualPathProvider.Combine(BasePath, destinationFileName));
File.Copy(assemblyFileName, destinationPath, true); 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) { public DependencyDescriptor GetDescriptor(string moduleName) {
var dependency = ReadDependencies().SingleOrDefault(d => d.Name == assemblyName); 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) { if (dependency == null) {
return true; return true;
} }
@@ -59,15 +115,15 @@ namespace Orchard.FileSystems.Dependencies {
return (File.GetLastWriteTimeUtc(existingFileName) < File.GetLastWriteTimeUtc(assemblyFileName)); return (File.GetLastWriteTimeUtc(existingFileName) < File.GetLastWriteTimeUtc(assemblyFileName));
} }
private void StoreDepencyInformation(string name, string fileName) { private void StoreDepencyInformation(DependencyDescriptor descriptor) {
var dependencies = ReadDependencies().ToList(); var dependencies = ReadDependencies().ToList();
int index = dependencies.FindIndex(d => d.ModuleName == descriptor.ModuleName);
var dependency = dependencies.SingleOrDefault(d => d.Name == name); if (index < 0) {
if (dependency == null) { dependencies.Add(descriptor);
dependency = new DependencyDescritpor { Name = name, FileName = fileName }; }
dependencies.Add(dependency); else {
dependencies[index] = descriptor;
} }
dependency.FileName = fileName;
WriteDependencies(dependencies); WriteDependencies(dependencies);
} }
@@ -75,7 +131,7 @@ namespace Orchard.FileSystems.Dependencies {
public Assembly LoadAssembly(string assemblyName) { public Assembly LoadAssembly(string assemblyName) {
_virtualPathProvider.CreateDirectory(BasePath); _virtualPathProvider.CreateDirectory(BasePath);
var dependency = ReadDependencies().SingleOrDefault(d => d.Name == assemblyName); var dependency = ReadDependencies().SingleOrDefault(d => d.ModuleName == assemblyName);
if (dependency == null) if (dependency == null)
return null; return null;
@@ -85,30 +141,32 @@ namespace Orchard.FileSystems.Dependencies {
return Assembly.Load(Path.GetFileNameWithoutExtension(dependency.FileName)); return Assembly.Load(Path.GetFileNameWithoutExtension(dependency.FileName));
} }
private class DependencyDescritpor { private IEnumerable<DependencyDescriptor> ReadDependencies() {
public string Name { get; set; }
public string FileName { get; set; }
}
private IEnumerable<DependencyDescritpor> ReadDependencies() {
if (!_virtualPathProvider.FileExists(PersistencePath)) if (!_virtualPathProvider.FileExists(PersistencePath))
return Enumerable.Empty<DependencyDescritpor>(); return Enumerable.Empty<DependencyDescriptor>();
using (var stream = _virtualPathProvider.OpenFile(PersistencePath)) { using (var stream = _virtualPathProvider.OpenFile(PersistencePath)) {
XDocument document = XDocument.Load(stream); XDocument document = XDocument.Load(stream);
return document return document
.Elements(ns("Dependencies")) .Elements(ns("Dependencies"))
.Elements(ns("Dependency")) .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(); .ToList();
} }
} }
private void WriteDependencies(IEnumerable<DependencyDescritpor> dependencies) { private void WriteDependencies(IEnumerable<DependencyDescriptor> dependencies) {
var document = new XDocument(); var document = new XDocument();
document.Add(new XElement(ns("Dependencies"))); document.Add(new XElement(ns("Dependencies")));
var elements = dependencies.Select(d => new XElement("Dependency", 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))); new XElement(ns("FileName"), d.FileName)));
document.Root.Add(elements); document.Root.Add(elements);

View File

@@ -341,8 +341,11 @@
<Compile Include="Data\DataModule.cs" /> <Compile Include="Data\DataModule.cs" />
<Compile Include="Data\Orderable.cs" /> <Compile Include="Data\Orderable.cs" />
<Compile Include="Environment\DefaultOrchardShell.cs" /> <Compile Include="Environment\DefaultOrchardShell.cs" />
<Compile Include="Environment\Extensions\Loaders\MergedReadOnlyStreams.cs" />
<Compile Include="Environment\ICustomVirtualPathProvider.cs" />
<Compile Include="Environment\Extensions\Loaders\WebFormsExtensionsVirtualPathProvider.cs" /> <Compile Include="Environment\Extensions\Loaders\WebFormsExtensionsVirtualPathProvider.cs" />
<Compile Include="Environment\Extensions\Loaders\WebFormsExtensionsVirtualFile.cs" /> <Compile Include="Environment\Extensions\Loaders\WebFormsExtensionsVirtualFile.cs" />
<Compile Include="Environment\Extensions\IExtensionManagerEvents.cs" />
<Compile Include="Environment\IHostEnvironment.cs" /> <Compile Include="Environment\IHostEnvironment.cs" />
<Compile Include="FileSystems\Dependencies\IDependenciesFolder.cs" /> <Compile Include="FileSystems\Dependencies\IDependenciesFolder.cs" />
<Compile Include="Environment\Extensions\Loaders\ProbingExtensionLoader.cs" /> <Compile Include="Environment\Extensions\Loaders\ProbingExtensionLoader.cs" />