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:
Louis DeJardin
2010-04-15 00:52:58 -07:00
parent a302fefbdf
commit 122ea0b629
11 changed files with 440 additions and 131 deletions

View File

@@ -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);

View File

@@ -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>();
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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" />

View File

@@ -136,7 +136,7 @@ namespace Orchard.Setup.Controllers {
_tenantManager.SaveSettings(shellSettings);
_orchardHost.Reinitialize();
_orchardHost.Reinitialize_Obsolete();
// redirect to the welcome page.
return Redirect("~/");

View File

@@ -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 {

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
}
}
}

View File

@@ -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>(),
};
}
}
}

View File

@@ -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; }