mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Adding a specific component to orchetrate the creation of a shell context
--HG-- branch : dev
This commit is contained in:
@@ -25,8 +25,7 @@ namespace Orchard.Specs.Hosting
|
||||
webHost.Execute(() =>
|
||||
{
|
||||
var output = new StringWriter();
|
||||
var worker = new Worker(details, output);
|
||||
HttpRuntime.ProcessRequest(worker);
|
||||
HttpRuntime.ProcessRequest(new Worker(details, output));
|
||||
details.ResponseText = output.ToString();
|
||||
});
|
||||
|
||||
@@ -35,8 +34,8 @@ namespace Orchard.Specs.Hosting
|
||||
|
||||
class Worker : SimpleWorkerRequest
|
||||
{
|
||||
private RequestDetails _details;
|
||||
private TextWriter _output;
|
||||
private readonly RequestDetails _details;
|
||||
private readonly TextWriter _output;
|
||||
|
||||
public Worker(RequestDetails details, TextWriter output)
|
||||
: base(details.Page, details.Query, output)
|
||||
@@ -60,3 +59,4 @@ namespace Orchard.Specs.Hosting
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Autofac;
|
||||
using Autofac.Builder;
|
||||
using Autofac.Core;
|
||||
using Autofac.Core.Registration;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.ShellBuilders;
|
||||
using Orchard.Environment.Topology;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
|
||||
namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
[TestFixture]
|
||||
public class DefaultShellContextFactoryTests {
|
||||
private IContainer _container;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<DefaultShellContextFactory>().As<IShellContextFactory>();
|
||||
builder.RegisterSource(new MockServiceSource());
|
||||
_container = builder.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NormalExecutionReturnsExpectedObjects() {
|
||||
var settings = new ShellSettings {Name = "Default"};
|
||||
var topologyDescriptor = new ShellTopologyDescriptor {SerialNumber = 6655321};
|
||||
var topology = new ShellTopology();
|
||||
ILifetimeScope shellLifetimeScope;
|
||||
|
||||
_container.Mock<ITopologyDescriptorCache>()
|
||||
.Setup(x => x.Fetch("Default"))
|
||||
.Returns(topologyDescriptor);
|
||||
|
||||
_container.Mock<ICompositionStrategy>()
|
||||
.Setup(x => x.Compose(topologyDescriptor))
|
||||
.Returns(topology);
|
||||
|
||||
_container.Mock<IShellContainerFactory>()
|
||||
.Setup(x => x.CreateContainer(topology))
|
||||
.Returns(shellLifetimeScope = _container.BeginLifetimeScope("shell"));
|
||||
|
||||
_container.Mock<ITopologyDescriptorProvider>()
|
||||
.Setup(x => x.GetTopologyDescriptor())
|
||||
.Returns(topologyDescriptor);
|
||||
|
||||
var factory = _container.Resolve<IShellContextFactory>();
|
||||
|
||||
var context = factory.Create(settings);
|
||||
|
||||
Assert.That(context.Settings, Is.SameAs(settings));
|
||||
Assert.That(context.TopologyDescriptor, Is.SameAs(topologyDescriptor));
|
||||
Assert.That(context.Topology, Is.SameAs(topology));
|
||||
Assert.That(context.LifetimeScope, Is.SameAs(shellLifetimeScope));
|
||||
Assert.That(context.Shell, Is.SameAs(shellLifetimeScope.Resolve<IOrchardShell>()));
|
||||
}
|
||||
}
|
||||
|
||||
class MockServiceSource : IRegistrationSource {
|
||||
public IEnumerable<IComponentRegistration> RegistrationsFor(
|
||||
Service service,
|
||||
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor) {
|
||||
|
||||
var swt = service as IServiceWithType;
|
||||
if (swt == null)
|
||||
yield break;
|
||||
var st = swt.ServiceType;
|
||||
|
||||
if (st.IsGenericType && st.GetGenericTypeDefinition() == typeof(Mock<>)) {
|
||||
yield return RegistrationBuilder.ForType(st).SingleInstance().CreateRegistration();
|
||||
}
|
||||
else if (st.IsInterface) {
|
||||
yield return RegistrationBuilder.ForDelegate(
|
||||
(ctx, p) => {
|
||||
Trace.WriteLine(string.Format("Mocking {0}", st));
|
||||
var mt = typeof(Mock<>).MakeGenericType(st);
|
||||
var m = (Mock)ctx.Resolve(mt);
|
||||
return m.Object;
|
||||
})
|
||||
.As(service)
|
||||
.SingleInstance()
|
||||
.CreateRegistration();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MockExtensions {
|
||||
public static Mock<T> Mock<T>(this IContainer container) where T : class {
|
||||
return container.Resolve<Mock<T>>();
|
||||
}
|
||||
}
|
||||
}
|
@@ -163,6 +163,7 @@
|
||||
<Compile Include="Environment\DefaultOrchardHostTests.cs" />
|
||||
<Compile Include="Environment\DefaultOrchardShellTests.cs" />
|
||||
<Compile Include="Environment\OrchardStarterTests.cs" />
|
||||
<Compile Include="Environment\ShellBuilders\DefaultShellContextFactoryTests.cs" />
|
||||
<Compile Include="Environment\ShellBuilders\SetupShellContainerFactoryTests.cs" />
|
||||
<Compile Include="Environment\TestDependencies\TestDependency.cs" />
|
||||
<Compile Include="Environment\Topology\DefaultTopologyDescriptorCacheTests.cs" />
|
||||
|
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Autofac;
|
||||
@@ -5,6 +6,8 @@ using Autofac.Integration.Web;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.ShellBuilders;
|
||||
using Orchard.Environment.Topology;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
using Orchard.Extensions;
|
||||
using Orchard.Mvc;
|
||||
using Orchard.Mvc.ViewEngines;
|
||||
@@ -22,6 +25,9 @@ namespace Orchard.Environment {
|
||||
public DefaultOrchardHost(
|
||||
IContainerProvider containerProvider,
|
||||
ITenantManager tenantManager,
|
||||
ITopologyDescriptorCache topologyDescriptorCache,
|
||||
ICompositionStrategy compositionStrategy,
|
||||
IShellContainerFactory shellContainerFactory,
|
||||
ControllerBuilder controllerBuilder,
|
||||
IEnumerable<IShellContainerFactory_Obsolete> shellContainerFactories) {
|
||||
_containerProvider = containerProvider;
|
||||
@@ -126,6 +132,7 @@ namespace Orchard.Environment {
|
||||
finally {
|
||||
containerProvider.EndRequestLifetime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,50 @@
|
||||
using Autofac;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Topology;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
|
||||
namespace Orchard.Environment.ShellBuilders {
|
||||
public class DefaultShellContextFactory : IShellContextFactory {
|
||||
private readonly ITopologyDescriptorCache _topologyDescriptorCache;
|
||||
private readonly ICompositionStrategy _compositionStrategy;
|
||||
private readonly IShellContainerFactory _shellContainerFactory;
|
||||
|
||||
public DefaultShellContextFactory(
|
||||
ITopologyDescriptorCache topologyDescriptorCache,
|
||||
ICompositionStrategy compositionStrategy,
|
||||
IShellContainerFactory shellContainerFactory) {
|
||||
_topologyDescriptorCache = topologyDescriptorCache;
|
||||
_compositionStrategy = compositionStrategy;
|
||||
_shellContainerFactory = shellContainerFactory;
|
||||
}
|
||||
|
||||
public ShellContext Create(ShellSettings settings) {
|
||||
var cachedTopology = _topologyDescriptorCache.Fetch(settings.Name);
|
||||
// handle null-(e.g. cache miss)
|
||||
|
||||
var topology = _compositionStrategy.Compose(cachedTopology);
|
||||
var shellScope = _shellContainerFactory.CreateContainer(topology);
|
||||
|
||||
ShellTopologyDescriptor currentTopology;
|
||||
using (var standaloneEnvironment = new StandaloneEnvironment(shellScope)) {
|
||||
var topologyDescriptorProvider = standaloneEnvironment.Resolve<ITopologyDescriptorProvider>();
|
||||
currentTopology = topologyDescriptorProvider.GetTopologyDescriptor();
|
||||
}
|
||||
|
||||
if (cachedTopology.SerialNumber != currentTopology.SerialNumber) {
|
||||
_topologyDescriptorCache.Store(settings.Name, currentTopology);
|
||||
topology = _compositionStrategy.Compose(currentTopology);
|
||||
shellScope = _shellContainerFactory.CreateContainer(topology);
|
||||
}
|
||||
|
||||
var shell = shellScope.Resolve<IOrchardShell>();
|
||||
return new ShellContext {
|
||||
Settings = settings,
|
||||
TopologyDescriptor = currentTopology,
|
||||
Topology = topology,
|
||||
LifetimeScope = shellScope,
|
||||
Shell = shellScope.Resolve<IOrchardShell>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
using Orchard.Environment.Configuration;
|
||||
|
||||
namespace Orchard.Environment.ShellBuilders {
|
||||
public interface IShellContextFactory {
|
||||
ShellContext Create(ShellSettings settings);
|
||||
}
|
||||
}
|
13
src/Orchard/Environment/ShellBuilders/ShellContext.cs
Normal file
13
src/Orchard/Environment/ShellBuilders/ShellContext.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Autofac;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
|
||||
namespace Orchard.Environment.ShellBuilders {
|
||||
public class ShellContext {
|
||||
public ShellSettings Settings { get; set; }
|
||||
public ShellTopologyDescriptor TopologyDescriptor { get; set; }
|
||||
public ShellTopology Topology { get; set; }
|
||||
public ILifetimeScope LifetimeScope { get; set; }
|
||||
public IOrchardShell Shell { get; set; }
|
||||
}
|
||||
}
|
@@ -167,6 +167,9 @@
|
||||
<Compile Include="Environment\Configuration\DefaultTenantManager.cs" />
|
||||
<Compile Include="Environment\Configuration\ITenantManager.cs" />
|
||||
<Compile Include="Environment\AutofacUtil\ContainerUpdater.cs" />
|
||||
<Compile Include="Environment\ShellBuilders\DefaultShellContextFactory.cs" />
|
||||
<Compile Include="Environment\ShellBuilders\IShellContextFactory.cs" />
|
||||
<Compile Include="Environment\ShellBuilders\ShellContext.cs" />
|
||||
<Compile Include="Environment\Topology\DefaultTopologyDescriptorCache.cs" />
|
||||
<Compile Include="Environment\Topology\ICompositionStrategy.cs" />
|
||||
<Compile Include="Environment\Topology\ITopologyDescriptorProvider.cs" />
|
||||
|
Reference in New Issue
Block a user