Incremental changes towards enabling setup module

Setup controller can render initial screen
SafeMode container factory moved into Orchard.Setup module
ShellBuilders namespace files compacted a bit
Core feature named "Orchard.Framework" and is not used in setup mode

--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-04-17 21:33:36 -07:00
parent a137d84732
commit 71e019a0b8
22 changed files with 198 additions and 265 deletions

View File

@@ -45,7 +45,7 @@ namespace Orchard.Tests.Environment {
builder.RegisterType<DefaultOrchardHost>().As<IOrchardHost>().SingleInstance();
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>();
builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>();
builder.RegisterType<DefaultShellContextFactory>().As<IShellContextFactory>();
builder.RegisterType<ShellContextFactory>().As<IShellContextFactory>();
builder.RegisterInstance(_controllerBuilder);
builder.RegisterInstance(_routeCollection);
builder.RegisterInstance(_modelBinderDictionary);

View File

@@ -24,14 +24,16 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterType<DefaultShellContainerFactory>().As<IShellContainerFactory>();
builder.RegisterType<ShellContainerFactory>().As<IShellContainerFactory>();
builder.RegisterType<ComponentForHostContainer>();
_container = builder.Build();
}
ShellSettings CreateSettings() {
return new ShellSettings {Name = "Default"};
}
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>(),
@@ -53,9 +55,10 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[Test]
public void ShouldReturnChildLifetimeScopeNamedShell() {
var settings = CreateSettings();
var topology = CreateTopology();
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, topology);
Assert.That(shellContainer.Tag, Is.EqualTo("shell"));
@@ -68,12 +71,13 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[Test]
public void ControllersAreRegisteredAsKeyedServices() {
var settings = CreateSettings();
var topology = CreateTopology(
WithModule<TestModule>(),
WithController<TestController>("foo", "bar"));
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, topology);
var controllers = shellContainer.Resolve<IIndex<string, IController>>();
var controller = controllers["foo|bar"];
Assert.That(controller, Is.Not.Null);
@@ -86,12 +90,13 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[Test]
public void ModulesAreResolvedAndRegistered() {
var settings = CreateSettings();
var topology = CreateTopology(
WithModule<TestModule>(),
WithController<TestController>("foo", "bar"));
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, topology);
var controllerMetas = shellContainer.Resolve<IIndex<string, Meta<IController>>>();
var metadata = controllerMetas["foo|bar"].Metadata;
@@ -108,11 +113,12 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[Test]
public void ModulesMayResolveHostServices() {
var settings = CreateSettings();
var topology = CreateTopology(
WithModule<ModuleUsingThatComponent>());
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, topology);
Assert.That(shellContainer.Resolve<string>(), Is.EqualTo("Module was loaded"));
}
@@ -134,11 +140,12 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[Test]
public void DependenciesAreResolvable() {
var settings = CreateSettings();
var topology = CreateTopology(
WithDependency<TestDependency>());
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, topology);
var testDependency = shellContainer.Resolve<ITestDependency>();
Assert.That(testDependency, Is.Not.Null);
@@ -153,30 +160,33 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[Test]
public void ExtraInformationCanDropIntoProperties() {
var settings = CreateSettings();
var topology = CreateTopology(
WithDependency<TestDependency2>());
topology.Dependencies.Single().FeatureDescriptor =
new FeatureDescriptor { Name = "Hello" };
topology.Dependencies.Single().Feature =
new Feature { Descriptor = new FeatureDescriptor { Name = "Hello" } };
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, 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"));
Assert.That(testDependency2.Feature.Descriptor, Is.Not.Null);
Assert.That(testDependency2.Feature.Descriptor.Name, Is.EqualTo("Hello"));
}
public class TestDependency2 : ITestDependency {
public FeatureDescriptor FeatureDescriptor { get; set; }
public Feature Feature { get; set; }
}
[Test]
public void ParametersMayOrMayNotBeUsedAsPropertiesAndConstructorParameters() {
var settings = CreateSettings();
var topology = CreateTopology(
WithDependency<TestDependency3>());
@@ -188,7 +198,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
};
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, topology);
var testDependency = shellContainer.Resolve<ITestDependency>();
Assert.That(testDependency, Is.Not.Null);
@@ -220,12 +230,13 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[Test]
public void DynamicProxyIsInEffect() {
var settings = CreateSettings();
var topology = CreateTopology(
WithModule<ProxModule>(),
WithDependency<ProxDependency>());
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, topology);
var testDependency = shellContainer.Resolve<IProxDependency>();
Assert.That(testDependency.Hello(), Is.EqualTo("Foo"));
@@ -233,7 +244,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
var topology2 = CreateTopology(
WithDependency<ProxDependency>());
var shellContainer2 = factory.CreateContainer(topology2);
var shellContainer2 = factory.CreateContainer(settings, topology2);
var testDependency2 = shellContainer2.Resolve<IProxDependency>();
Assert.That(testDependency2.Hello(), Is.EqualTo("World"));
@@ -269,10 +280,11 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[Test]
public void DynamicProxyAndShellSettingsAreResolvableToSameInstances() {
var settings = CreateSettings();
var topology = CreateTopology();
var factory = _container.Resolve<IShellContainerFactory>();
var shellContainer = factory.CreateContainer(topology);
var shellContainer = factory.CreateContainer(settings, topology);
var proxa = shellContainer.Resolve<DynamicProxyContext>();
var proxb = shellContainer.Resolve<DynamicProxyContext>();
@@ -286,7 +298,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
var topology2 = CreateTopology();
var shellContainer2 = factory.CreateContainer(topology2);
var shellContainer2 = factory.CreateContainer(settings, topology2);
var proxa2 = shellContainer2.Resolve<DynamicProxyContext>();
var proxb2 = shellContainer2.Resolve<DynamicProxyContext>();

View File

@@ -17,7 +17,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterType<DefaultShellContextFactory>().As<IShellContextFactory>();
builder.RegisterType<ShellContextFactory>().As<IShellContextFactory>();
builder.RegisterAutoMocking(Moq.MockBehavior.Strict);
_container = builder.Build();
}
@@ -38,7 +38,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
.Returns(topology);
_container.Mock<IShellContainerFactory>()
.Setup(x => x.CreateContainer(topology))
.Setup(x => x.CreateContainer(settings, topology))
.Returns(shellLifetimeScope );
_container.Mock<ITopologyDescriptorManager>()
@@ -65,7 +65,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
.Returns(topology);
_container.Mock<IShellContainerFactory>()
.Setup(x => x.CreateContainer(topology))
.Setup(x => x.CreateContainer(It.IsAny<ShellSettings>(), topology))
.Returns(_container.BeginLifetimeScope("shell"));
var factory = _container.Resolve<IShellContextFactory>();

View File

@@ -1,45 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
using NUnit.Framework;
using Orchard.Environment;
using Orchard.Environment.ShellBuilders;
using Orchard.Mvc.Filters;
using Orchard.Mvc.ViewEngines;
namespace Orchard.Tests.Environment.ShellBuilders {
[TestFixture]
public class SetupShellContainerFactoryTests {
private IContainer _hostContainer;
[SetUp]
public void Init() {
_hostContainer = OrchardStarter.CreateHostContainer(builder => {
builder.RegisterInstance(new ViewEngineCollection());
builder.RegisterInstance(new RouteCollection());
builder.RegisterInstance(new ModelBinderDictionary());
});
}
[Test, Ignore("Can't be made to work until module settings and infrastructres implemented")]
public void FactoryShouldCreateContainerThatProvidesShell() {
var factory = new SafeModeShellContainerFactory(_hostContainer);
var shellContainer = factory.CreateContainer(null);
Assert.That(shellContainer, Is.Not.Null);
var shell = shellContainer.Resolve<IOrchardShell>();
Assert.That(shell, Is.Not.Null);
}
[Test, Ignore("Can't be made to work until module settings and infrastructres implemented")]
public void ShellContainerShouldProvideLayoutViewEngine() {
var factory = new SafeModeShellContainerFactory(_hostContainer);
var shellContainer = factory.CreateContainer(null);
var viewEngineFilter = shellContainer.Resolve<IEnumerable<IFilterProvider>>()
.Single(f=>f is ViewEngineFilter);
Assert.That(viewEngineFilter, Is.Not.Null);
}
}
}

View File

@@ -1,21 +0,0 @@
using System.Linq;
using System.Web.Mvc;
using NUnit.Framework;
using Orchard.Environment.Extensions;
using Orchard.Mvc;
using Autofac.Core;
namespace Orchard.Tests.Mvc {
[TestFixture] public class OrchardControllerIdentificationStrategyTests {
[Test]
public void IdentificationStrategyAddsAssemblyNameAsAreaPrefixToControllerNames() {
var strategy = new OrchardControllerIdentificationStrategy(Enumerable.Empty<ExtensionEntry>());
var service = strategy.ServiceForControllerType(typeof (StrategyTestingController));
Assert.That(service, Is.TypeOf<NamedService>());
Assert.That(((NamedService)service).ServiceName, Is.EqualTo("controller.orchard.framework.tests.strategytesting"));
}
}
public class StrategyTestingController:Controller {
}
}

View File

@@ -6,6 +6,7 @@ using System.Web.Routing;
using NUnit.Framework;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.Environment.Topology.Models;
using Orchard.Mvc.Routes;
namespace Orchard.Tests.Mvc.Routes {
@@ -13,8 +14,31 @@ namespace Orchard.Tests.Mvc.Routes {
public class StandardExtensionRouteProviderTests {
[Test]
public void ExtensionDisplayNameShouldBeUsedInBothStandardRoutes() {
var stubManager = new StubExtensionManager();
var routeProvider = new StandardExtensionRouteProvider(stubManager);
var topology = new ShellTopology {
Controllers = new[] {
new ControllerTopology {
AreaName ="Long.Name.Foo",
Feature =new Feature {
Descriptor=new FeatureDescriptor {
Extension=new ExtensionDescriptor {
DisplayName="Foo"
}
}
}
},
new ControllerTopology {
AreaName ="Long.Name.Bar",
Feature =new Feature {
Descriptor=new FeatureDescriptor {
Extension=new ExtensionDescriptor {
DisplayName="Bar"
}
}
}
}
}
};
var routeProvider = new StandardExtensionRouteProvider(topology);
var routes = new List<RouteDescriptor>();
routeProvider.GetRoutes(routes);

View File

@@ -167,7 +167,6 @@
<Compile Include="Environment\ShellBuilders\DefaultShellContainerFactoryTests.cs" />
<Compile Include="Environment\ShellBuilders\DefaultShellContextFactoryTests.cs" />
<Compile Include="Utility\ContainerExtensions.cs" />
<Compile Include="Environment\ShellBuilders\SetupShellContainerFactoryTests.cs" />
<Compile Include="Environment\TestDependencies\TestDependency.cs" />
<Compile Include="Environment\Topology\DefaultTopologyDescriptorCacheTests.cs" />
<Compile Include="EventsTests.cs" />
@@ -179,7 +178,6 @@
<Compile Include="Logging\LoggingModuleTests.cs" />
<Compile Include="Mvc\ModelBinders\KeyedListModelBinderTests.cs" />
<Compile Include="Mvc\OrchardControllerFactoryTests.cs" />
<Compile Include="Mvc\OrchardControllerIdentificationStrategyTests.cs" />
<Compile Include="Mvc\RouteCollectionPublisherTests.cs" />
<Compile Include="Mvc\Routes\StandardExtensionRouteProviderTests.cs" />
<Compile Include="Tasks\SweepGeneratorTests.cs" />

View File

@@ -31,6 +31,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=2.1.13.813, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.ComponentModel.DataAnnotations">
@@ -66,6 +70,7 @@
<Compile Include="Controllers\SetupController.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Routes.cs" />
<Compile Include="SetupMode.cs" />
<Compile Include="ViewModels\SetupViewModel.cs" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,18 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Routing;
using Autofac;
using Autofac.Builder;
using Autofac.Core;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.Data.Builders;
using Orchard.Environment.AutofacUtil;
using Orchard.Environment.AutofacUtil.DynamicProxy2;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
using Orchard.Localization;
using Orchard.Mvc;
@@ -27,30 +20,14 @@ using Orchard.UI.PageClass;
using Orchard.UI.PageTitle;
using Orchard.UI.Zones;
namespace Orchard.Environment.ShellBuilders {
public class SafeModeShellContainerFactory : IShellContainerFactory_Obsolete {
private readonly IContainer _container;
namespace Orchard.Setup {
public class SetupMode : Module {
protected override void Load(ContainerBuilder builder) {
public SafeModeShellContainerFactory(IContainer container) {
_container = container;
}
public ILifetimeScope CreateContainer(ShellSettings settings) {
// when you have settings the setup container factory is not in effect
if (settings != null) {
return null;
}
var dynamicProxyContext = new DynamicProxyContext();
var shellScope = _container.BeginLifetimeScope();
var builder = new ContainerUpdater();
// standard services needed in safe mode
builder.RegisterInstance(dynamicProxyContext);
builder.RegisterType<DefaultOrchardShell>().As<IOrchardShell>().InstancePerLifetimeScope();
// standard services needed in setup mode
builder.RegisterModule(new MvcModule());
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope();
builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>().InstancePerLifetimeScope();
builder.RegisterType<MvcModule>().As<IModule>().InstancePerLifetimeScope();
builder.RegisterType<WebFormsViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope();
builder.RegisterType<ViewEngineFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
builder.RegisterType<ThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
@@ -60,39 +37,16 @@ namespace Orchard.Environment.ShellBuilders {
builder.RegisterType<Notifier>().As<INotifier>().InstancePerLifetimeScope();
builder.RegisterType<NotifyFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
builder.RegisterType<SessionFactoryBuilder>().As<ISessionFactoryBuilder>().InstancePerLifetimeScope();
// safe mode specific implementations of needed service interfaces
// setup mode specific implementations of needed service interfaces
builder.RegisterType<NullHackInstallationGenerator>().As<IHackInstallationGenerator>().InstancePerLifetimeScope();
builder.RegisterType<SafeModeThemeService>().As<IThemeService>().InstancePerLifetimeScope();
builder.RegisterType<SafeModeText>().As<IText>().InstancePerLifetimeScope();
builder.RegisterType<SafeModeSiteService>().As<ISiteService>().InstancePerLifetimeScope();
// yes, this is brutal, and if you are reading this, I sincerely apologize.
var dependencies = Assembly.Load("Orchard.Setup")
.GetExportedTypes()
.Where(type => type.IsClass && !type.IsAbstract && typeof(IDependency).IsAssignableFrom(type));
foreach (var serviceType in dependencies) {
var registrar = builder.RegisterType(serviceType).EnableDynamicProxy(dynamicProxyContext).InstancePerLifetimeScope();
foreach (var interfaceType in serviceType.GetInterfaces()) {
if (typeof(IDependency).IsAssignableFrom(interfaceType)) {
registrar = registrar.As(interfaceType);
if (typeof(ISingletonDependency).IsAssignableFrom(interfaceType)) {
registrar = registrar.SingleInstance();
}
else if (typeof(ITransientDependency).IsAssignableFrom(interfaceType)) {
registrar = registrar.InstancePerDependency();
}
}
}
}
builder.Update(shellScope);
var modulesUpdater = new ContainerUpdater();
foreach (var module in _container.Resolve<IEnumerable<IModule>>()) {
modulesUpdater.RegisterModule(module);
}
modulesUpdater.Update(shellScope);
return shellScope;
}
class SafeModeText : IText {
public LocalizedString Get(string textHint, params object[] args) {
if (args == null || args.Length == 0) {
@@ -170,5 +124,4 @@ namespace Orchard.Environment.ShellBuilders {
}
}
}
}

View File

@@ -36,37 +36,16 @@ namespace Orchard.Environment {
.SelectMany(extensionDescriptor => extensionDescriptor.Features)
.Where(featureDescriptor => IsFeatureEnabledInTopology(featureDescriptor, topologyDescriptor));
var features = _extensionManager.LoadFeatures(featureDescriptors).Concat(CoreFeatures());
var features = _extensionManager.LoadFeatures(featureDescriptors);
return new ShellTopology {
Modules = BuildTopology<ModuleTopology>(features, IsModule, BuildModule),
Dependencies = BuildTopology<DependencyTopology>(features, IsDependency, (t, f) => BuildDependency(t, f, topologyDescriptor)),
Dependencies = BuildTopology(features, IsDependency, (t, f) => BuildDependency(t, f, topologyDescriptor)),
Controllers = BuildTopology<ControllerTopology>(features, IsController, BuildController),
Records = BuildTopology<RecordTopology>(features, IsRecord, BuildRecord),
};
}
private static IEnumerable<Feature> CoreFeatures() {
var frameworkTypes = typeof(OrchardStarter).Assembly.GetExportedTypes();
var core = new Feature {
Descriptor = new FeatureDescriptor {
Name = "Core",
Extension = new ExtensionDescriptor {
Name = "Core",
DisplayName = "Core",
AntiForgery = "enabled",
},
},
ExportedTypes = frameworkTypes.Where(t => t.IsClass && !t.IsAbstract),
//ExportedTypes = new[] {
// typeof (ContentTypeRecord),
// typeof (ContentItemRecord),
// typeof (ContentItemVersionRecord),
//},
};
return new[] { core };
}
private static bool IsFeatureEnabledInTopology(FeatureDescriptor featureDescriptor, ShellTopologyDescriptor topologyDescriptor) {

View File

@@ -13,7 +13,7 @@ using Orchard.Utility.Extensions;
namespace Orchard.Environment {
public class DefaultOrchardHost : IOrchardHost {
private readonly IContainerProvider _containerProvider;
//private readonly IContainerProvider _containerProvider;
private readonly ControllerBuilder _controllerBuilder;
private readonly ITenantManager _tenantManager;
@@ -22,11 +22,11 @@ namespace Orchard.Environment {
private IEnumerable<ShellContext> _current;
public DefaultOrchardHost(
IContainerProvider containerProvider,
//IContainerProvider containerProvider,
ITenantManager tenantManager,
IShellContextFactory shellContextFactory,
ControllerBuilder controllerBuilder) {
_containerProvider = containerProvider;
//_containerProvider = containerProvider;
_tenantManager = tenantManager;
_shellContextFactory = shellContextFactory;
_controllerBuilder = controllerBuilder;
@@ -43,7 +43,7 @@ namespace Orchard.Environment {
Logger.Information("Initializing");
ViewEngines.Engines.Insert(0, LayoutViewEngine.CreateShim());
_controllerBuilder.SetControllerFactory(new OrchardControllerFactory());
ServiceLocator.SetLocator(t => _containerProvider.RequestLifetime.Resolve(t));
//ServiceLocator.SetLocator(t => _containerProvider.RequestLifetime.Resolve(t));
BuildCurrent();
}
@@ -84,8 +84,10 @@ namespace Orchard.Environment {
return context;
});
}
return new[] {CreateSetupContext()};
var setupContext = CreateSetupContext();
setupContext.Shell.Activate();
return new[] {setupContext};
}
ShellContext CreateSetupContext() {
@@ -103,7 +105,7 @@ namespace Orchard.Environment {
}
protected virtual void EndRequest() {
_containerProvider.EndRequestLifetime();
//_containerProvider.EndRequestLifetime();
}

View File

@@ -119,6 +119,16 @@ namespace Orchard.Environment.Extensions {
}
public Feature LoadFeature(FeatureDescriptor featureDescriptor) {
if (featureDescriptor.Name == "Orchard.Framework") {
return new Feature {
Descriptor = featureDescriptor,
ExportedTypes =
typeof(OrchardStarter).Assembly.GetExportedTypes()
.Where(t => t.IsClass && !t.IsAbstract)
.ToArray()
};
}
var featureName = featureDescriptor.Name;
string extensionName = GetExtensionForFeature(featureName);
if (extensionName == null) throw new ArgumentException(T("Feature ") + featureName + T(" was not found in any of the installed extensions"));

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Web.Hosting;
using Autofac;
using Autofac.Configuration;
using Autofac.Core;
using Autofac.Integration.Web;
using Orchard.Environment.AutofacUtil;
using Orchard.Environment.Configuration;
@@ -29,7 +31,7 @@ namespace Orchard.Environment {
{
builder.RegisterType<DefaultTenantManager>().As<ITenantManager>().SingleInstance();
builder.RegisterType<DefaultShellContextFactory>().As<IShellContextFactory>().SingleInstance();
builder.RegisterType<ShellContextFactory>().As<IShellContextFactory>().SingleInstance();
{
builder.RegisterType<DefaultTopologyDescriptorCache>().As<ITopologyDescriptorCache>().SingleInstance();
@@ -58,7 +60,7 @@ namespace Orchard.Environment {
}
}
builder.RegisterType<DefaultShellContainerFactory>().As<IShellContainerFactory>().SingleInstance();
builder.RegisterType<ShellContainerFactory>().As<IShellContainerFactory>().SingleInstance();
}
}
@@ -82,13 +84,55 @@ namespace Orchard.Environment {
if (File.Exists(optionalHostConfig))
builder.RegisterModule(new ConfigurationSettingsReader(ConfigurationSettingsReader.DefaultSectionName, optionalHostConfig));
var container = builder.Build();
builder
.Register(ctx => new LifetimeScopeContainer(ctx.Resolve<ILifetimeScope>()))
.As<IContainer>()
.InstancePerMatchingLifetimeScope("shell");
var updater = new ContainerUpdater();
updater.RegisterInstance(container);
updater.Update(container);
return builder.Build();
}
return container;
public class LifetimeScopeContainer : IContainer {
private readonly ILifetimeScope _lifetimeScope;
public LifetimeScopeContainer(ILifetimeScope lifetimeScope) {
_lifetimeScope = lifetimeScope;
}
public object Resolve(IComponentRegistration registration, IEnumerable<Parameter> parameters) {
return _lifetimeScope.Resolve(registration, parameters);
}
public IComponentRegistry ComponentRegistry {
get { return _lifetimeScope.ComponentRegistry; }
}
public void Dispose() {
}
public ILifetimeScope BeginLifetimeScope() {
return _lifetimeScope.BeginLifetimeScope();
}
public ILifetimeScope BeginLifetimeScope(object tag) {
return _lifetimeScope.BeginLifetimeScope(tag);
}
public ILifetimeScope BeginLifetimeScope(Action<ContainerBuilder> configurationAction) {
return _lifetimeScope.BeginLifetimeScope(configurationAction);
}
public ILifetimeScope BeginLifetimeScope(object tag, Action<ContainerBuilder> configurationAction) {
return _lifetimeScope.BeginLifetimeScope(tag, configurationAction);
}
public IDisposer Disposer {
get { return _lifetimeScope.Disposer; }
}
public object Tag {
get { return _lifetimeScope.Tag; }
}
}
public static IOrchardHost CreateHost(Action<ContainerBuilder> registrations) {

View File

@@ -1,13 +0,0 @@
using Autofac;
using Orchard.Environment.Configuration;
using Orchard.Environment.Topology.Models;
namespace Orchard.Environment.ShellBuilders {
public interface IShellContainerFactory {
ILifetimeScope CreateContainer(ShellTopology topology);
}
public interface IShellContainerFactory_Obsolete {
ILifetimeScope CreateContainer(ShellSettings settings);
}
}

View File

@@ -1,7 +0,0 @@
using Orchard.Environment.Configuration;
namespace Orchard.Environment.ShellBuilders {
public interface IShellContextFactory {
ShellContext Create(ShellSettings settings);
}
}

View File

@@ -5,18 +5,25 @@ using Autofac;
using Autofac.Builder;
using Autofac.Core;
using Autofac.Features.Indexed;
using Autofac.Integration.Web.Mvc;
using Orchard.Environment.AutofacUtil.DynamicProxy2;
using Orchard.Environment.Configuration;
using Orchard.Environment.Topology.Models;
namespace Orchard.Environment.ShellBuilders {
public class DefaultShellContainerFactory : IShellContainerFactory {
public interface IShellContainerFactory {
ILifetimeScope CreateContainer(ShellSettings settings, ShellTopology topology);
}
public class ShellContainerFactory : IShellContainerFactory {
private readonly ILifetimeScope _lifetimeScope;
public DefaultShellContainerFactory(ILifetimeScope lifetimeScope) {
public ShellContainerFactory(ILifetimeScope lifetimeScope) {
_lifetimeScope = lifetimeScope;
}
public ILifetimeScope CreateContainer(ShellTopology topology) {
public ILifetimeScope CreateContainer(ShellSettings settings, ShellTopology topology) {
var intermediateScope = _lifetimeScope.BeginLifetimeScope(
builder => {
foreach (var item in topology.Modules) {
@@ -32,7 +39,8 @@ namespace Orchard.Environment.ShellBuilders {
var dynamicProxyContext = new DynamicProxyContext();
builder.Register(ctx => dynamicProxyContext);
builder.Register(ctx => topology.ShellSettings);
builder.Register(ctx => settings);
builder.Register(ctx => topology);
var moduleIndex = intermediateScope.Resolve<IIndex<Type, IModule>>();
foreach (var item in topology.Modules) {
@@ -42,7 +50,7 @@ namespace Orchard.Environment.ShellBuilders {
foreach (var item in topology.Dependencies) {
var registration = RegisterType(builder, item)
.EnableDynamicProxy(dynamicProxyContext)
.InstancePerDependency();
.InstancePerLifetimeScope();
foreach (var interfaceType in item.Type.GetInterfaces().Where(itf => typeof(IDependency).IsAssignableFrom(itf))) {
registration = registration.As(interfaceType);
@@ -62,19 +70,19 @@ namespace Orchard.Environment.ShellBuilders {
}
foreach (var item in topology.Controllers) {
var serviceKey = (item.AreaName + "/" + item.ControllerName).ToLowerInvariant();
RegisterType(builder, item)
.EnableDynamicProxy(dynamicProxyContext)
.Keyed<IController>(item.AreaName + "|" + item.ControllerName)
.InstancePerDependency();
.Keyed<IController>(serviceKey)
.InstancePerDependency()
.InjectActionInvoker();
}
});
}
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);
.WithProperty("Feature", item.Feature);
}
}
}

View File

@@ -1,19 +1,22 @@
using System;
using System.Linq;
using Autofac;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions.Models;
using Orchard.Environment.Topology;
using Orchard.Environment.Topology.Models;
using Orchard.Logging;
namespace Orchard.Environment.ShellBuilders {
public class DefaultShellContextFactory : IShellContextFactory {
public interface IShellContextFactory {
ShellContext Create(ShellSettings settings);
}
public class ShellContextFactory : IShellContextFactory {
private readonly ITopologyDescriptorCache _topologyDescriptorCache;
private readonly ICompositionStrategy _compositionStrategy;
private readonly IShellContainerFactory _shellContainerFactory;
public DefaultShellContextFactory(
public ShellContextFactory(
ITopologyDescriptorCache topologyDescriptorCache,
ICompositionStrategy compositionStrategy,
IShellContainerFactory shellContainerFactory) {
@@ -44,7 +47,7 @@ namespace Orchard.Environment.ShellBuilders {
// handle null-(e.g. cache miss)
var topology = _compositionStrategy.Compose(cachedDescriptor);
var shellScope = _shellContainerFactory.CreateContainer(topology);
var shellScope = _shellContainerFactory.CreateContainer(settings, topology);
ShellTopologyDescriptor currentDescriptor;
using (var standaloneEnvironment = new StandaloneEnvironment(shellScope)) {
@@ -57,7 +60,7 @@ namespace Orchard.Environment.ShellBuilders {
_topologyDescriptorCache.Store(settings.Name, currentDescriptor);
topology = _compositionStrategy.Compose(currentDescriptor);
shellScope = _shellContainerFactory.CreateContainer(topology);
shellScope = _shellContainerFactory.CreateContainer(settings, topology);
}
return new ShellContext {
@@ -79,7 +82,7 @@ namespace Orchard.Environment.ShellBuilders {
};
var topology = _compositionStrategy.Compose(descriptor);
var shellScope = _shellContainerFactory.CreateContainer(topology);
var shellScope = _shellContainerFactory.CreateContainer(settings, topology);
return new ShellContext {
Settings = settings,

View File

@@ -6,7 +6,6 @@ using Orchard.Environment.Extensions.Models;
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; }
@@ -16,9 +15,7 @@ namespace Orchard.Environment.Topology.Models {
public class ShellTopologyItem {
public Type Type { get; set; }
public Feature Feature { get; set; }
public ExtensionDescriptor ExtensionDescriptor { get; set; }
public FeatureDescriptor FeatureDescriptor { get; set; }
public ExtensionEntry ExtensionEntry { get; set; }
}
public class ModuleTopology : ShellTopologyItem {

View File

@@ -1,35 +1,15 @@
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
using Autofac.Integration.Web;
using Autofac.Integration.Web.Mvc;
using Orchard.Environment.AutofacUtil.DynamicProxy2;
using Orchard.Environment.Extensions;
using Orchard.Mvc.Filters;
using Autofac.Core;
namespace Orchard.Mvc {
public class MvcModule : Module {
private readonly IExtensionManager _extensionManager;
private readonly DynamicProxyContext _dynamicProxyContext;
public MvcModule(IExtensionManager extensionManager, DynamicProxyContext dynamicProxyContext) {
_extensionManager = extensionManager;
_dynamicProxyContext = dynamicProxyContext;
}
protected override void Load(ContainerBuilder moduleBuilder) {
var extensions = _extensionManager.ActiveExtensions_Obsolete();
var assemblies = extensions.Select(x => x.Assembly);
var actionInvokerService = new UniqueService();
moduleBuilder.RegisterType<FilterResolvingActionInvoker>().As(actionInvokerService).InstancePerDependency();
moduleBuilder.RegisterControllers(new OrchardControllerIdentificationStrategy(extensions), assemblies.ToArray())
.EnableDynamicProxy(_dynamicProxyContext)
.InjectActionInvoker(actionInvokerService).InstancePerDependency();
moduleBuilder.RegisterType<FilterResolvingActionInvoker>().As<IActionInvoker>().InstancePerDependency();
moduleBuilder.Register(ctx => HttpContextBaseFactory(ctx)).As<HttpContextBase>().InstancePerDependency();
moduleBuilder.Register(ctx => RequestContextFactory(ctx)).As<RequestContext>().InstancePerDependency();

View File

@@ -1,4 +1,3 @@
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
@@ -7,26 +6,28 @@ using Autofac.Integration.Web;
namespace Orchard.Mvc {
public class OrchardControllerFactory : DefaultControllerFactory {
public override IController CreateController(RequestContext requestContext, string controllerName) {
var routeData = requestContext.RouteData;
// Locate the container this route is bound against
var container = GetRequestContainer(routeData);
// Determine the area name for the request, and fall back to stock orchard controllers
var areaName = GetAreaName(routeData) ?? "Orchard";
var areaName = GetAreaName(routeData);
// Service name pattern matches the identification strategy
var serviceName = ("controller." + areaName + "." + controllerName).ToLowerInvariant();
var serviceKey = (areaName + "/" + controllerName).ToLowerInvariant();
// Now that the request container is known - try to resolve the controller
object controller;
NamedService service = new NamedService(serviceName, typeof(IController));
TypedParameter parameter = TypedParameter.From(requestContext);
var service = new KeyedService(serviceKey, typeof(IController));
// Locate the container this route is bound against
var container = GetRequestContainer(routeData);
if (container != null &&
container.TryResolve(service, new List<Parameter>{parameter}, out controller)) {
container.TryResolve(service, out controller)) {
return (IController)controller;
}
return base.CreateController(requestContext, controllerName);
}

View File

@@ -1,20 +1,26 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Environment.Extensions;
using Orchard.Environment.Topology.Models;
namespace Orchard.Mvc.Routes {
public class StandardExtensionRouteProvider : IRouteProvider {
private readonly IExtensionManager _extensionManager;
private readonly ShellTopology _topology;
public StandardExtensionRouteProvider(IExtensionManager extensionManager) {
_extensionManager = extensionManager;
public StandardExtensionRouteProvider(ShellTopology topology) {
_topology = topology;
}
public IEnumerable<RouteDescriptor> GetRoutes() {
foreach (var entry in _extensionManager.ActiveExtensions_Obsolete()) {
var areaName = entry.Descriptor.Name;
var displayName = entry.Descriptor.DisplayName ?? areaName;
var displayNamesPerArea = _topology.Controllers.GroupBy(
x => x.AreaName,
x => x.Feature.Descriptor.Extension.DisplayName);
foreach (var item in displayNamesPerArea) {
var areaName = item.Key;
var displayName = item.Distinct().Single();
yield return new RouteDescriptor {
Priority = -10,

View File

@@ -169,8 +169,7 @@
<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\ShellContextFactory.cs" />
<Compile Include="Environment\ShellBuilders\ShellContext.cs" />
<Compile Include="Environment\Topology\DefaultTopologyDescriptorCache.cs" />
<Compile Include="Environment\Topology\ICompositionStrategy.cs" />
@@ -178,9 +177,7 @@
<Compile Include="Environment\Topology\ITopologyDescriptorCache.cs" />
<Compile Include="Environment\Topology\Models\ShellTopology.cs" />
<Compile Include="Environment\Topology\Models\ShellTopologyDescriptor.cs" />
<Compile Include="Environment\ShellBuilders\DefaultShellContainerFactory.cs" />
<Compile Include="Environment\ShellBuilders\IShellContainerFactory.cs" />
<Compile Include="Environment\ShellBuilders\SafeModeShellContainerFactory.cs" />
<Compile Include="Environment\ShellBuilders\ShellContainerFactory.cs" />
<Compile Include="Environment\Configuration\ShellSettings.cs" />
<Compile Include="Environment\StandaloneEnvironment.cs" />
<Compile Include="Events\DefaultOrchardEventBus.cs" />