mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-19 18:27:55 +08:00
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:
@@ -31,7 +31,6 @@ namespace Orchard.Web {
|
||||
|
||||
RegisterRoutes(RouteTable.Routes);
|
||||
|
||||
HostingEnvironment.RegisterVirtualPathProvider(new WebFormsExtensionsVirtualPathProvider());
|
||||
_host = OrchardStarter.CreateHost(MvcSingletons);
|
||||
_host.Initialize();
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -0,0 +1,7 @@
|
||||
using Orchard.Events;
|
||||
|
||||
namespace Orchard.Environment.Extensions {
|
||||
public interface IExtensionManagerEvents : IEventHandler {
|
||||
void ModuleChanged(string moduleName);
|
||||
}
|
||||
}
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
7
src/Orchard/Environment/ICustomVirtualPathProvider.cs
Normal file
7
src/Orchard/Environment/ICustomVirtualPathProvider.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using System.Web.Hosting;
|
||||
|
||||
namespace Orchard.Environment {
|
||||
public interface ICustomVirtualPathProvider {
|
||||
VirtualPathProvider Instance { get; }
|
||||
}
|
||||
}
|
@@ -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<DefaultCacheHolder>().As<ICacheHolder>().SingleInstance();
|
||||
builder.RegisterType<DefaultHostEnvironment>().As<IHostEnvironment>().SingleInstance();
|
||||
builder.RegisterType<DefaultBuildManager>().As<IBuildManager>().SingleInstance();
|
||||
builder.RegisterType<WebFormsExtensionsVirtualPathProvider>().As<ICustomVirtualPathProvider>().SingleInstance();
|
||||
|
||||
RegisterVolatileProvider<WebSiteFolder, IWebSiteFolder>(builder);
|
||||
RegisterVolatileProvider<AppDataFolder, IAppDataFolder>(builder);
|
||||
@@ -117,6 +119,15 @@ namespace Orchard.Environment {
|
||||
|
||||
public static IOrchardHost CreateHost(Action<ContainerBuilder> 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>();
|
||||
}
|
||||
}
|
||||
|
@@ -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<DependencyDescritpor> ReadDependencies() {
|
||||
private IEnumerable<DependencyDescriptor> ReadDependencies() {
|
||||
if (!_virtualPathProvider.FileExists(PersistencePath))
|
||||
return Enumerable.Empty<DependencyDescritpor>();
|
||||
return Enumerable.Empty<DependencyDescriptor>();
|
||||
|
||||
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<DependencyDescritpor> dependencies) {
|
||||
private void WriteDependencies(IEnumerable<DependencyDescriptor> 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);
|
||||
|
||||
|
@@ -341,8 +341,11 @@
|
||||
<Compile Include="Data\DataModule.cs" />
|
||||
<Compile Include="Data\Orderable.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\WebFormsExtensionsVirtualFile.cs" />
|
||||
<Compile Include="Environment\Extensions\IExtensionManagerEvents.cs" />
|
||||
<Compile Include="Environment\IHostEnvironment.cs" />
|
||||
<Compile Include="FileSystems\Dependencies\IDependenciesFolder.cs" />
|
||||
<Compile Include="Environment\Extensions\Loaders\ProbingExtensionLoader.cs" />
|
||||
|
Reference in New Issue
Block a user