mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-12-03 20:13:52 +08:00
Reimplementing DefaultShellContainerFactory : IShellContainerFactory
Based on new interface which takes ShellTopology and returns ILifetimeScope Other partial changes to DefaultOrchardHost Several tests and web app currently broken --HG-- branch : dev
This commit is contained in:
@@ -33,7 +33,7 @@ namespace Orchard.Tests.Modules.Setup {
|
||||
//hostContainer.Resolve<IAppDataFolder>().SetBasePath(_tempFolder);
|
||||
|
||||
//var host = (DefaultOrchardHost)hostContainer.Resolve<IOrchardHost>();
|
||||
//_container = host.CreateShellContainer().BeginLifetimeScope();
|
||||
//_container = host.CreateShellContainer_Obsolete().BeginLifetimeScope();
|
||||
//var updater = new ContainerUpdater();
|
||||
//updater.RegisterType<SetupController>();
|
||||
//updater.Update(_container);
|
||||
|
||||
@@ -11,6 +11,9 @@ using NUnit.Framework;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.AutofacUtil;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.ShellBuilders;
|
||||
using Orchard.Environment.Topology;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
using Orchard.Mvc;
|
||||
using Orchard.Mvc.ModelBinders;
|
||||
using Orchard.Mvc.Routes;
|
||||
@@ -37,10 +40,11 @@ namespace Orchard.Tests.Environment {
|
||||
builder => {
|
||||
//builder.RegisterModule(new ImplicitCollectionSupportModule());
|
||||
builder.RegisterType<StubContainerProvider>().As<IContainerProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<StubCompositionStrategy>().As<ICompositionStrategy_Obsolete>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<StubCompositionStrategy>().As<ICompositionStrategy_Obsolete>().As<ICompositionStrategy>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<DefaultOrchardHost>().As<IOrchardHost>().SingleInstance();
|
||||
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>();
|
||||
builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>();
|
||||
builder.RegisterType<DefaultShellContextFactory>().As<IShellContextFactory>();
|
||||
builder.RegisterInstance(_controllerBuilder);
|
||||
builder.RegisterInstance(_routeCollection);
|
||||
builder.RegisterInstance(_modelBinderDictionary);
|
||||
@@ -48,6 +52,7 @@ namespace Orchard.Tests.Environment {
|
||||
builder.RegisterInstance(new StuExtensionManager()).As<IExtensionManager>();
|
||||
builder.RegisterInstance(new Mock<IHackInstallationGenerator>().Object);
|
||||
builder.RegisterInstance(new StubShellSettingsLoader()).As<ITenantManager>();
|
||||
builder.RegisterInstance(new Mock<ITopologyDescriptorCache>().Object);
|
||||
});
|
||||
_lifetime = _container.BeginLifetimeScope();
|
||||
var updater = new ContainerUpdater();
|
||||
@@ -103,7 +108,7 @@ namespace Orchard.Tests.Environment {
|
||||
Assert.That(_controllerBuilder.GetControllerFactory(), Is.TypeOf<OrchardControllerFactory>());
|
||||
}
|
||||
|
||||
public class StubCompositionStrategy : ICompositionStrategy_Obsolete {
|
||||
public class StubCompositionStrategy : ICompositionStrategy_Obsolete, ICompositionStrategy {
|
||||
public IEnumerable<Type> GetModuleTypes() {
|
||||
return Enumerable.Empty<Type>();
|
||||
}
|
||||
@@ -119,22 +124,26 @@ namespace Orchard.Tests.Environment {
|
||||
public IEnumerable<RecordDescriptor> GetRecordDescriptors() {
|
||||
return Enumerable.Empty<RecordDescriptor>();
|
||||
}
|
||||
|
||||
public ShellTopology Compose(ShellTopologyDescriptor descriptor) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DifferentShellInstanceShouldBeReturnedAfterEachCreate() {
|
||||
var host = (DefaultOrchardHost)_lifetime.Resolve<IOrchardHost>();
|
||||
var runtime1 = host.CreateShell();
|
||||
var runtime2 = host.CreateShell();
|
||||
var host = _lifetime.Resolve<IOrchardHost>();
|
||||
var runtime1 = host.CreateShell_Obsolete();
|
||||
var runtime2 = host.CreateShell_Obsolete();
|
||||
Assert.That(runtime1, Is.Not.SameAs(runtime2));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void NormalDependenciesShouldBeUniquePerRequestContainer() {
|
||||
var host = (DefaultOrchardHost)_lifetime.Resolve<IOrchardHost>();
|
||||
var container1 = host.CreateShellContainer();
|
||||
var container2 = host.CreateShellContainer();
|
||||
var host = _lifetime.Resolve<IOrchardHost>();
|
||||
var container1 = host.CreateShellContainer_Obsolete();
|
||||
var container2 = host.CreateShellContainer_Obsolete();
|
||||
var requestContainer1a = container1.BeginLifetimeScope();
|
||||
var requestContainer1b = container1.BeginLifetimeScope();
|
||||
var requestContainer2a = container2.BeginLifetimeScope();
|
||||
@@ -169,9 +178,9 @@ namespace Orchard.Tests.Environment {
|
||||
}
|
||||
[Test]
|
||||
public void SingletonDependenciesShouldBeUniquePerShell() {
|
||||
var host = (DefaultOrchardHost)_lifetime.Resolve<IOrchardHost>();
|
||||
var container1 = host.CreateShellContainer();
|
||||
var container2 = host.CreateShellContainer();
|
||||
var host = _lifetime.Resolve<IOrchardHost>();
|
||||
var container1 = host.CreateShellContainer_Obsolete();
|
||||
var container2 = host.CreateShellContainer_Obsolete();
|
||||
var requestContainer1a = container1.BeginLifetimeScope();
|
||||
var requestContainer1b = container1.BeginLifetimeScope();
|
||||
var requestContainer2a = container2.BeginLifetimeScope();
|
||||
@@ -192,9 +201,9 @@ namespace Orchard.Tests.Environment {
|
||||
}
|
||||
[Test]
|
||||
public void TransientDependenciesShouldBeUniquePerResolve() {
|
||||
var host = (DefaultOrchardHost)_lifetime.Resolve<IOrchardHost>();
|
||||
var container1 = host.CreateShellContainer();
|
||||
var container2 = host.CreateShellContainer();
|
||||
var host = _lifetime.Resolve<IOrchardHost>();
|
||||
var container1 = host.CreateShellContainer_Obsolete();
|
||||
var container2 = host.CreateShellContainer_Obsolete();
|
||||
var requestContainer1a = container1.BeginLifetimeScope();
|
||||
var requestContainer1b = container1.BeginLifetimeScope();
|
||||
var requestContainer2a = container2.BeginLifetimeScope();
|
||||
@@ -229,4 +238,17 @@ namespace Orchard.Tests.Environment {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class TextExtensions {
|
||||
public static ILifetimeScope CreateShellContainer_Obsolete(this IOrchardHost host) {
|
||||
return ((DefaultOrchardHost) host)
|
||||
.Current
|
||||
.Single(x => x.Settings.Name == "Default")
|
||||
.LifetimeScope;
|
||||
}
|
||||
|
||||
public static IOrchardShell CreateShell_Obsolete(this IOrchardHost host) {
|
||||
return host.CreateShellContainer_Obsolete().Resolve<IOrchardShell>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using Autofac;
|
||||
using Autofac.Core;
|
||||
using Autofac.Core.Lifetime;
|
||||
using Autofac.Features.Indexed;
|
||||
using Autofac.Features.Metadata;
|
||||
using Castle.Core.Interceptor;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Environment.AutofacUtil.DynamicProxy2;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.ShellBuilders;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
using Orchard.Extensions;
|
||||
|
||||
namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
[TestFixture]
|
||||
public class DefaultShellContainerFactoryTests {
|
||||
private IContainer _container;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<DefaultShellContainerFactory>().As<IShellContainerFactory>();
|
||||
builder.RegisterType<ComponentForHostContainer>();
|
||||
_container = builder.Build();
|
||||
}
|
||||
|
||||
ShellTopology CreateTopology(params ShellTopologyItem[] items) {
|
||||
return new ShellTopology {
|
||||
ShellSettings = new ShellSettings { Name = "Default" },
|
||||
Modules = items.OfType<ModuleTopology>(),
|
||||
Dependencies = items.OfType<DependencyTopology>(),
|
||||
Controllers = items.OfType<ControllerTopology>(),
|
||||
Records = items.OfType<RecordTopology>(),
|
||||
};
|
||||
}
|
||||
|
||||
ModuleTopology WithModule<T>() {
|
||||
return new ModuleTopology { Type = typeof(T) };
|
||||
}
|
||||
|
||||
ControllerTopology WithController<T>(string areaName, string controllerName) {
|
||||
return new ControllerTopology { Type = typeof(T), AreaName = areaName, ControllerName = controllerName };
|
||||
}
|
||||
|
||||
DependencyTopology WithDependency<T>() {
|
||||
return new DependencyTopology { Type = typeof(T), Parameters = Enumerable.Empty<TopologyParameter>() };
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldReturnChildLifetimeScopeNamedShell() {
|
||||
var topology = CreateTopology();
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
|
||||
Assert.That(shellContainer.Tag, Is.EqualTo("shell"));
|
||||
|
||||
var scope = (LifetimeScope)shellContainer;
|
||||
Assert.That(scope.RootLifetimeScope, Is.SameAs(_container.Resolve<ILifetimeScope>()));
|
||||
Assert.That(scope.RootLifetimeScope, Is.Not.SameAs(shellContainer.Resolve<ILifetimeScope>()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void ControllersAreRegisteredAsKeyedServices() {
|
||||
var topology = CreateTopology(
|
||||
WithModule<TestModule>(),
|
||||
WithController<TestController>("foo", "bar"));
|
||||
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
var controllers = shellContainer.Resolve<IIndex<string, IController>>();
|
||||
var controller = controllers["foo|bar"];
|
||||
Assert.That(controller, Is.Not.Null);
|
||||
Assert.That(controller, Is.InstanceOf<TestController>());
|
||||
}
|
||||
|
||||
public class TestController : Controller {
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ModulesAreResolvedAndRegistered() {
|
||||
var topology = CreateTopology(
|
||||
WithModule<TestModule>(),
|
||||
WithController<TestController>("foo", "bar"));
|
||||
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
|
||||
var controllerMetas = shellContainer.Resolve<IIndex<string, Meta<IController>>>();
|
||||
var metadata = controllerMetas["foo|bar"].Metadata;
|
||||
|
||||
Assert.That(metadata["Hello"], Is.EqualTo("World"));
|
||||
}
|
||||
|
||||
|
||||
public class TestModule : Module {
|
||||
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
|
||||
registration.Metadata["Hello"] = "World";
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ModulesMayResolveHostServices() {
|
||||
var topology = CreateTopology(
|
||||
WithModule<ModuleUsingThatComponent>());
|
||||
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
Assert.That(shellContainer.Resolve<string>(), Is.EqualTo("Module was loaded"));
|
||||
}
|
||||
|
||||
public class ComponentForHostContainer {
|
||||
|
||||
}
|
||||
|
||||
public class ModuleUsingThatComponent : Module {
|
||||
private readonly ComponentForHostContainer _di;
|
||||
|
||||
public ModuleUsingThatComponent(ComponentForHostContainer di) {
|
||||
_di = di;
|
||||
}
|
||||
|
||||
protected override void Load(ContainerBuilder builder) {
|
||||
builder.RegisterInstance("Module was loaded");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DependenciesAreResolvable() {
|
||||
var topology = CreateTopology(
|
||||
WithDependency<TestDependency>());
|
||||
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
|
||||
var testDependency = shellContainer.Resolve<ITestDependency>();
|
||||
Assert.That(testDependency, Is.Not.Null);
|
||||
Assert.That(testDependency, Is.InstanceOf<TestDependency>());
|
||||
}
|
||||
|
||||
public interface ITestDependency : IDependency {
|
||||
|
||||
}
|
||||
public class TestDependency : ITestDependency {
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtraInformationCanDropIntoProperties() {
|
||||
var topology = CreateTopology(
|
||||
WithDependency<TestDependency2>());
|
||||
|
||||
topology.Dependencies.Single().FeatureDescriptor =
|
||||
new FeatureDescriptor { Name = "Hello" };
|
||||
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
|
||||
var testDependency = shellContainer.Resolve<ITestDependency>();
|
||||
Assert.That(testDependency, Is.Not.Null);
|
||||
Assert.That(testDependency, Is.InstanceOf<TestDependency2>());
|
||||
|
||||
var testDependency2 = (TestDependency2)testDependency;
|
||||
Assert.That(testDependency2.FeatureDescriptor, Is.Not.Null);
|
||||
Assert.That(testDependency2.FeatureDescriptor.Name, Is.EqualTo("Hello"));
|
||||
}
|
||||
|
||||
public class TestDependency2 : ITestDependency {
|
||||
public FeatureDescriptor FeatureDescriptor { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParametersMayOrMayNotBeUsedAsPropertiesAndConstructorParameters() {
|
||||
var topology = CreateTopology(
|
||||
WithDependency<TestDependency3>());
|
||||
|
||||
topology.Dependencies.Single().Parameters =
|
||||
new[] {
|
||||
new TopologyParameter {Name = "alpha", Value = "-a-"},
|
||||
new TopologyParameter {Name = "Beta", Value = "-b-"},
|
||||
new TopologyParameter {Name = "Gamma", Value = "-g-"},
|
||||
};
|
||||
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
|
||||
var testDependency = shellContainer.Resolve<ITestDependency>();
|
||||
Assert.That(testDependency, Is.Not.Null);
|
||||
Assert.That(testDependency, Is.InstanceOf<TestDependency3>());
|
||||
|
||||
var testDependency3 = (TestDependency3)testDependency;
|
||||
Assert.That(testDependency3.GetAlpha(), Is.EqualTo("-a-"));
|
||||
Assert.That(testDependency3.Beta, Is.EqualTo("-b-"));
|
||||
Assert.That(testDependency3.Delta, Is.EqualTo("y"));
|
||||
}
|
||||
|
||||
public class TestDependency3 : ITestDependency {
|
||||
private readonly string _alpha;
|
||||
|
||||
public TestDependency3(string alpha) {
|
||||
_alpha = alpha;
|
||||
Beta = "x";
|
||||
Delta = "y";
|
||||
}
|
||||
|
||||
public string Beta { get; set; }
|
||||
public string Delta { get; set; }
|
||||
|
||||
public string GetAlpha() {
|
||||
return _alpha;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void DynamicProxyIsInEffect() {
|
||||
var topology = CreateTopology(
|
||||
WithModule<ProxModule>(),
|
||||
WithDependency<ProxDependency>());
|
||||
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
|
||||
var testDependency = shellContainer.Resolve<IProxDependency>();
|
||||
Assert.That(testDependency.Hello(), Is.EqualTo("Foo"));
|
||||
|
||||
var topology2 = CreateTopology(
|
||||
WithDependency<ProxDependency>());
|
||||
|
||||
var shellContainer2 = factory.CreateContainer(topology2);
|
||||
|
||||
var testDependency2 = shellContainer2.Resolve<IProxDependency>();
|
||||
Assert.That(testDependency2.Hello(), Is.EqualTo("World"));
|
||||
}
|
||||
|
||||
public interface IProxDependency : IDependency {
|
||||
string Hello();
|
||||
}
|
||||
|
||||
public class ProxDependency : IProxDependency {
|
||||
public virtual string Hello() {
|
||||
return "World";
|
||||
}
|
||||
}
|
||||
|
||||
public class ProxIntercept : IInterceptor {
|
||||
public void Intercept(IInvocation invocation) {
|
||||
invocation.ReturnValue = "Foo";
|
||||
}
|
||||
}
|
||||
|
||||
public class ProxModule : Module {
|
||||
protected override void Load(ContainerBuilder builder) {
|
||||
builder.RegisterType<ProxIntercept>();
|
||||
}
|
||||
|
||||
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
|
||||
if (registration.Activator.LimitType == typeof(ProxDependency)) {
|
||||
registration.InterceptedBy<ProxIntercept>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DynamicProxyAndShellSettingsAreResolvableToSameInstances() {
|
||||
var topology = CreateTopology();
|
||||
|
||||
var factory = _container.Resolve<IShellContainerFactory>();
|
||||
var shellContainer = factory.CreateContainer(topology);
|
||||
|
||||
var proxa = shellContainer.Resolve<DynamicProxyContext>();
|
||||
var proxb = shellContainer.Resolve<DynamicProxyContext>();
|
||||
var setta = shellContainer.Resolve<ShellSettings>();
|
||||
var settb = shellContainer.Resolve<ShellSettings>();
|
||||
|
||||
Assert.That(proxa, Is.Not.Null);
|
||||
Assert.That(proxa, Is.SameAs(proxb));
|
||||
Assert.That(setta, Is.Not.Null);
|
||||
Assert.That(setta, Is.SameAs(settb));
|
||||
|
||||
|
||||
var topology2 = CreateTopology();
|
||||
var shellContainer2 = factory.CreateContainer(topology2);
|
||||
|
||||
var proxa2 = shellContainer2.Resolve<DynamicProxyContext>();
|
||||
var proxb2 = shellContainer2.Resolve<DynamicProxyContext>();
|
||||
var setta2 = shellContainer2.Resolve<ShellSettings>();
|
||||
var settb2 = shellContainer2.Resolve<ShellSettings>();
|
||||
|
||||
Assert.That(proxa2, Is.Not.Null);
|
||||
Assert.That(proxa2, Is.SameAs(proxb2));
|
||||
Assert.That(setta2, Is.Not.Null);
|
||||
Assert.That(setta2, Is.SameAs(settb2));
|
||||
|
||||
Assert.That(proxa, Is.Not.SameAs(proxa2));
|
||||
Assert.That(setta, Is.Not.SameAs(setta2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,6 +163,7 @@
|
||||
<Compile Include="Environment\DefaultOrchardHostTests.cs" />
|
||||
<Compile Include="Environment\DefaultOrchardShellTests.cs" />
|
||||
<Compile Include="Environment\OrchardStarterTests.cs" />
|
||||
<Compile Include="Environment\ShellBuilders\DefaultShellContainerFactoryTests.cs" />
|
||||
<Compile Include="Environment\ShellBuilders\DefaultShellContextFactoryTests.cs" />
|
||||
<Compile Include="Environment\ShellBuilders\SetupShellContainerFactoryTests.cs" />
|
||||
<Compile Include="Environment\TestDependencies\TestDependency.cs" />
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace Orchard.Setup.Controllers {
|
||||
|
||||
_tenantManager.SaveSettings(shellSettings);
|
||||
|
||||
_orchardHost.Reinitialize();
|
||||
_orchardHost.Reinitialize_Obsolete();
|
||||
|
||||
// redirect to the welcome page.
|
||||
return Redirect("~/");
|
||||
|
||||
@@ -11,48 +11,43 @@ using Orchard.Environment.Topology.Models;
|
||||
using Orchard.Extensions;
|
||||
using Orchard.Mvc;
|
||||
using Orchard.Mvc.ViewEngines;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace Orchard.Environment {
|
||||
public class DefaultOrchardHost : IOrchardHost {
|
||||
private readonly IContainerProvider _containerProvider;
|
||||
private readonly ControllerBuilder _controllerBuilder;
|
||||
private readonly IEnumerable<IShellContainerFactory_Obsolete> _shellContainerFactories;
|
||||
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private IOrchardShell _current;
|
||||
private readonly IShellContextFactory _shellContextFactory;
|
||||
|
||||
private IEnumerable<ShellContext> _current;
|
||||
|
||||
public DefaultOrchardHost(
|
||||
IContainerProvider containerProvider,
|
||||
ITenantManager tenantManager,
|
||||
ITopologyDescriptorCache topologyDescriptorCache,
|
||||
ICompositionStrategy compositionStrategy,
|
||||
IShellContainerFactory shellContainerFactory,
|
||||
ControllerBuilder controllerBuilder,
|
||||
IEnumerable<IShellContainerFactory_Obsolete> shellContainerFactories) {
|
||||
IShellContextFactory shellContextFactory,
|
||||
ControllerBuilder controllerBuilder) {
|
||||
_containerProvider = containerProvider;
|
||||
_tenantManager = tenantManager;
|
||||
_shellContextFactory = shellContextFactory;
|
||||
_controllerBuilder = controllerBuilder;
|
||||
_shellContainerFactories = shellContainerFactories;
|
||||
}
|
||||
|
||||
|
||||
public IOrchardShell Current {
|
||||
get { return _current; }
|
||||
public IList<ShellContext> Current {
|
||||
get { return BuildCurrent().ToReadOnlyCollection(); }
|
||||
}
|
||||
|
||||
|
||||
void IOrchardHost.Initialize() {
|
||||
ViewEngines.Engines.Insert(0, LayoutViewEngine.CreateShim());
|
||||
_controllerBuilder.SetControllerFactory(new OrchardControllerFactory());
|
||||
ServiceLocator.SetLocator(t => _containerProvider.RequestLifetime.Resolve(t));
|
||||
|
||||
CreateAndActivateShell();
|
||||
BuildCurrent();
|
||||
}
|
||||
|
||||
void IOrchardHost.Reinitialize() {
|
||||
void IOrchardHost.Reinitialize_Obsolete() {
|
||||
_current = null;
|
||||
//CreateAndActivateShell();
|
||||
}
|
||||
|
||||
|
||||
@@ -65,30 +60,30 @@ namespace Orchard.Environment {
|
||||
}
|
||||
|
||||
IStandaloneEnvironment IOrchardHost.CreateStandaloneEnvironment(ShellSettings shellSettings) {
|
||||
var shellContainer = CreateShellContainer(shellSettings);
|
||||
return new StandaloneEnvironment(shellContainer);
|
||||
var shellContext = _shellContextFactory.Create(shellSettings);
|
||||
return new StandaloneEnvironment(shellContext.LifetimeScope);
|
||||
}
|
||||
|
||||
protected virtual void CreateAndActivateShell() {
|
||||
IEnumerable<ShellContext> GetCurrent() {
|
||||
lock (this) {
|
||||
if (_current != null) {
|
||||
return;
|
||||
}
|
||||
return _current ?? (_current = BuildCurrent());
|
||||
}
|
||||
}
|
||||
|
||||
var shellContainer = CreateShellContainer();
|
||||
var shell = shellContainer.Resolve<IOrchardShell>();
|
||||
shell.Activate();
|
||||
_current = shell;
|
||||
IEnumerable<ShellContext> BuildCurrent() {
|
||||
return CreateAndActivate().ToArray();
|
||||
}
|
||||
|
||||
// Activate extensions inside shell container
|
||||
HackSimulateExtensionActivation(shellContainer);
|
||||
IEnumerable<ShellContext> CreateAndActivate() {
|
||||
foreach(var settings in _tenantManager.LoadSettings()) {
|
||||
var context = _shellContextFactory.Create(settings);
|
||||
context.Shell.Activate();
|
||||
yield return context;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void BeginRequest() {
|
||||
if (_current == null) {
|
||||
CreateAndActivateShell();
|
||||
}
|
||||
BuildCurrent();
|
||||
}
|
||||
|
||||
protected virtual void EndRequest() {
|
||||
@@ -96,31 +91,6 @@ namespace Orchard.Environment {
|
||||
}
|
||||
|
||||
|
||||
public virtual IOrchardShell CreateShell() {
|
||||
return CreateShellContainer().Resolve<IOrchardShell>();
|
||||
}
|
||||
|
||||
public virtual ILifetimeScope CreateShellContainer() {
|
||||
var settings = _tenantManager.LoadSettings();
|
||||
if (settings.Any()) {
|
||||
//TEMP: multi-tenancy not implemented yet
|
||||
var shellContainer = CreateShellContainer(settings.Single());
|
||||
if (shellContainer != null)
|
||||
return shellContainer;
|
||||
}
|
||||
return CreateShellContainer(null);
|
||||
}
|
||||
|
||||
private ILifetimeScope CreateShellContainer(ShellSettings shellSettings) {
|
||||
foreach (var factory in _shellContainerFactories) {
|
||||
var container = factory.CreateContainer(shellSettings);
|
||||
if (container != null) {
|
||||
return container;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void HackSimulateExtensionActivation(ILifetimeScope shellContainer) {
|
||||
var containerProvider = new FiniteContainerProvider(shellContainer);
|
||||
try {
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Orchard.Environment {
|
||||
/// <summary>
|
||||
/// Called when configuration changes requires the shell topology to be reloaded and applied
|
||||
/// </summary>
|
||||
void Reinitialize();
|
||||
void Reinitialize_Obsolete();
|
||||
|
||||
/// <summary>
|
||||
/// Called each time a request begins to offer a just-in-time reinitialization point
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Orchard.Environment {
|
||||
// a single default host implementation is needed for bootstrapping a web app domain
|
||||
builder.RegisterType<DefaultOrchardHost>().As<IOrchardHost>().SingleInstance();
|
||||
builder.RegisterType<DefaultCompositionStrategy>().As<ICompositionStrategy_Obsolete>().SingleInstance();
|
||||
builder.RegisterType<DefaultShellContainerFactory>().As<IShellContainerFactory_Obsolete>().SingleInstance();
|
||||
builder.RegisterType<DefaultShellContainerFactory>().As<IShellContainerFactory>().SingleInstance();
|
||||
builder.RegisterType<AppDataFolder>().As<IAppDataFolder>().SingleInstance();
|
||||
builder.RegisterType<DefaultTenantManager>().As<ITenantManager>().SingleInstance();
|
||||
builder.RegisterType<SafeModeShellContainerFactory>().As<IShellContainerFactory_Obsolete>().SingleInstance();
|
||||
|
||||
@@ -1,70 +1,80 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Autofac;
|
||||
using Autofac.Builder;
|
||||
using Autofac.Core;
|
||||
using Orchard.Environment.AutofacUtil;
|
||||
using Autofac.Features.Indexed;
|
||||
using Orchard.Environment.AutofacUtil.DynamicProxy2;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
|
||||
namespace Orchard.Environment.ShellBuilders {
|
||||
public class DefaultShellContainerFactory : IShellContainerFactory_Obsolete {
|
||||
private readonly IContainer _container;
|
||||
private readonly ICompositionStrategy_Obsolete _compositionStrategy;
|
||||
public class DefaultShellContainerFactory : IShellContainerFactory {
|
||||
private readonly ILifetimeScope _lifetimeScope;
|
||||
|
||||
public DefaultShellContainerFactory(IContainer container, ICompositionStrategy_Obsolete compositionStrategy) {
|
||||
_container = container;
|
||||
_compositionStrategy = compositionStrategy;
|
||||
public DefaultShellContainerFactory(ILifetimeScope lifetimeScope) {
|
||||
_lifetimeScope = lifetimeScope;
|
||||
}
|
||||
|
||||
public virtual ILifetimeScope CreateContainer(ShellSettings settings) {
|
||||
// null settings means we need to defer to the setup container factory
|
||||
if (settings == null) {
|
||||
return null;
|
||||
}
|
||||
public ILifetimeScope CreateContainer(ShellTopology topology) {
|
||||
var intermediateScope = _lifetimeScope.BeginLifetimeScope(
|
||||
builder => {
|
||||
foreach (var item in topology.Modules) {
|
||||
RegisterType(builder, item)
|
||||
.Keyed<IModule>(item.Type)
|
||||
.InstancePerDependency();
|
||||
}
|
||||
});
|
||||
|
||||
var dynamicProxyContext = new DynamicProxyContext();
|
||||
return intermediateScope.BeginLifetimeScope(
|
||||
"shell",
|
||||
builder => {
|
||||
var dynamicProxyContext = new DynamicProxyContext();
|
||||
|
||||
// add module types to container being built
|
||||
var addingModulesAndServices = new ContainerUpdater();
|
||||
addingModulesAndServices.RegisterInstance(settings).As<ShellSettings>();
|
||||
addingModulesAndServices.RegisterInstance(dynamicProxyContext);
|
||||
addingModulesAndServices.RegisterType<DefaultOrchardShell>().As<IOrchardShell>().SingleInstance();
|
||||
builder.Register(ctx => dynamicProxyContext);
|
||||
builder.Register(ctx => topology.ShellSettings);
|
||||
|
||||
foreach (var moduleType in _compositionStrategy.GetModuleTypes()) {
|
||||
addingModulesAndServices.RegisterType(moduleType).As<IModule>().InstancePerLifetimeScope();
|
||||
}
|
||||
var moduleIndex = intermediateScope.Resolve<IIndex<Type, IModule>>();
|
||||
foreach (var item in topology.Modules) {
|
||||
builder.RegisterModule(moduleIndex[item.Type]);
|
||||
}
|
||||
|
||||
// add components by the IDependency interfaces they expose
|
||||
foreach (var serviceType in _compositionStrategy.GetDependencyTypes()) {
|
||||
var registrar = addingModulesAndServices.RegisterType(serviceType)
|
||||
.EnableDynamicProxy(dynamicProxyContext)
|
||||
.InstancePerLifetimeScope();
|
||||
foreach (var item in topology.Dependencies) {
|
||||
var registration = RegisterType(builder, item)
|
||||
.EnableDynamicProxy(dynamicProxyContext)
|
||||
.InstancePerDependency();
|
||||
|
||||
foreach (var interfaceType in serviceType.GetInterfaces()) {
|
||||
if (typeof(IDependency).IsAssignableFrom(interfaceType)) {
|
||||
registrar = registrar.As(interfaceType);
|
||||
if (typeof(ISingletonDependency).IsAssignableFrom(interfaceType)) {
|
||||
registrar = registrar.SingleInstance();
|
||||
foreach (var interfaceType in item.Type.GetInterfaces().Where(itf => typeof(IDependency).IsAssignableFrom(itf))) {
|
||||
registration = registration.As(interfaceType);
|
||||
if (typeof(ISingletonDependency).IsAssignableFrom(interfaceType)) {
|
||||
registration = registration.InstancePerMatchingLifetimeScope("shell");
|
||||
}
|
||||
else if (typeof(ITransientDependency).IsAssignableFrom(interfaceType)) {
|
||||
registration = registration.InstancePerDependency();
|
||||
}
|
||||
}
|
||||
else if (typeof(ITransientDependency).IsAssignableFrom(interfaceType)) {
|
||||
registrar = registrar.InstancePerDependency();
|
||||
|
||||
foreach (var parameter in item.Parameters) {
|
||||
registration = registration
|
||||
.WithParameter(parameter.Name, parameter.Value)
|
||||
.WithProperty(parameter.Name, parameter.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var shellScope = _container.BeginLifetimeScope("shell");
|
||||
addingModulesAndServices.Update(shellScope);
|
||||
foreach (var item in topology.Controllers) {
|
||||
RegisterType(builder, item)
|
||||
.EnableDynamicProxy(dynamicProxyContext)
|
||||
.Keyed<IController>(item.AreaName + "|" + item.ControllerName)
|
||||
.InstancePerDependency();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// instantiate and register modules on container being built
|
||||
var modules = shellScope.Resolve<IEnumerable<IModule>>();
|
||||
var addingModules = new ContainerUpdater();
|
||||
foreach (var module in modules) {
|
||||
addingModules.RegisterModule(module);
|
||||
}
|
||||
|
||||
addingModules.Update(shellScope);
|
||||
|
||||
return shellScope;
|
||||
private IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle> RegisterType(ContainerBuilder builder, ShellTopologyItem item) {
|
||||
return builder.RegisterType(item.Type)
|
||||
.WithProperty("ExtensionEntry", item.ExtensionEntry)
|
||||
.WithProperty("FeatureDescriptor", item.FeatureDescriptor)
|
||||
.WithProperty("ExtensionDescriptor", item.ExtensionDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,14 +37,13 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
shellScope = _shellContainerFactory.CreateContainer(topology);
|
||||
}
|
||||
|
||||
var shell = shellScope.Resolve<IOrchardShell>();
|
||||
return new ShellContext {
|
||||
Settings = settings,
|
||||
TopologyDescriptor = currentTopology,
|
||||
Topology = topology,
|
||||
LifetimeScope = shellScope,
|
||||
Shell = shellScope.Resolve<IOrchardShell>(),
|
||||
};
|
||||
}
|
||||
Settings = settings,
|
||||
TopologyDescriptor = currentTopology,
|
||||
Topology = topology,
|
||||
LifetimeScope = shellScope,
|
||||
Shell = shellScope.Resolve<IOrchardShell>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Extensions;
|
||||
|
||||
namespace Orchard.Environment.Topology.Models {
|
||||
public class ShellTopology {
|
||||
public ShellSettings ShellSettings { get; set; }
|
||||
public IEnumerable<ModuleTopology> Modules { get; set; }
|
||||
public IEnumerable<DependencyTopology> Dependencies { get; set; }
|
||||
public IEnumerable<ControllerTopology> Controllers { get; set; }
|
||||
@@ -32,4 +34,4 @@ namespace Orchard.Environment.Topology.Models {
|
||||
public class RecordTopology : ShellTopologyItem {
|
||||
public string TableName { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user