From 6a5536dd32725214162825a2a730da93197fd564 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Thu, 2 Sep 2010 16:34:17 -0700 Subject: [PATCH] Additional incremental work towards removing redundant layers. --HG-- branch : dev --- .../Hosting/Orchard.Web/Global.asax.cs | 2 +- .../DefaultWorkContextAccessorTests.cs | 20 +++--- .../Orchard.Setup/Services/SetupService.cs | 3 +- src/Orchard/Commands/CommandHostAgent.cs | 2 +- .../Environment/DefaultHostContainer.cs | 64 +------------------ src/Orchard/Environment/DefaultOrchardHost.cs | 5 +- .../Environment/DefaultWorkContextAccessor.cs | 14 +++- .../Environment/FiniteContainerProvider.cs | 25 -------- src/Orchard/Environment/IContextualizable.cs | 7 -- src/Orchard/Environment/IOrchardHost.cs | 2 +- .../ShellBuilders/ShellContextFactory.cs | 2 +- .../Environment/StandaloneEnvironment.cs | 25 -------- .../State/DefaultProcessingEngine.cs | 2 +- src/Orchard/IWorkContextAccessor.cs | 5 +- .../Localization/LocalizationUtilities.cs | 4 +- src/Orchard/Mvc/Html/ContainerExtensions.cs | 10 ++- src/Orchard/Mvc/OrchardControllerFactory.cs | 23 +++---- src/Orchard/Mvc/Routes/ShellRoute.cs | 64 ++++++------------- .../Mvc/ViewEngines/Razor/WebViewPage.cs | 11 +--- src/Orchard/Orchard.Framework.csproj | 3 - src/Orchard/Tasks/SweepGenerator.cs | 2 +- src/Orchard/WorkContextExtensions.cs | 38 ++++++++++- 22 files changed, 117 insertions(+), 216 deletions(-) delete mode 100644 src/Orchard/Environment/FiniteContainerProvider.cs delete mode 100644 src/Orchard/Environment/IContextualizable.cs delete mode 100644 src/Orchard/Environment/StandaloneEnvironment.cs diff --git a/src/Orchard.Specs/Hosting/Orchard.Web/Global.asax.cs b/src/Orchard.Specs/Hosting/Orchard.Web/Global.asax.cs index 5d3043358..b73d82ac7 100644 --- a/src/Orchard.Specs/Hosting/Orchard.Web/Global.asax.cs +++ b/src/Orchard.Specs/Hosting/Orchard.Web/Global.asax.cs @@ -44,7 +44,7 @@ namespace Orchard.Specs.Hosting.Orchard.Web { _host.ReloadExtensions(); } - public static IStandaloneEnvironment CreateStandaloneEnvironment(string name) { + public static IWorkContextScope CreateStandaloneEnvironment(string name) { var settings = _hostContainer.Resolve().LoadSettings().SingleOrDefault(x => x.Name == name); return Host.CreateStandaloneEnvironment(settings); } diff --git a/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs b/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs index 7165afc1e..8edd2de91 100644 --- a/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs +++ b/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs @@ -37,7 +37,7 @@ namespace Orchard.Tests.Environment { var accessor = _container.Resolve(); var httpContext = new StubHttpContext(); - var workContextScope = accessor.CreateContextScope(httpContext); + var workContextScope = accessor.CreateWorkContextScope(httpContext); Assert.That(workContextScope.WorkContext, Is.Not.Null); var workContext = accessor.GetContext(httpContext); @@ -48,11 +48,11 @@ namespace Orchard.Tests.Environment { public void DifferentHttpContextWillHoldDifferentWorkContext() { var accessor = _container.Resolve(); var httpContext1 = new StubHttpContext(); - var workContextScope1 = accessor.CreateContextScope(httpContext1); + var workContextScope1 = accessor.CreateWorkContextScope(httpContext1); var workContext1 = accessor.GetContext(httpContext1); var httpContext2 = new StubHttpContext(); - var workContextScope2 = accessor.CreateContextScope(httpContext2); + var workContextScope2 = accessor.CreateWorkContextScope(httpContext2); var workContext2 = accessor.GetContext(httpContext2); Assert.That(workContext1, Is.Not.Null); @@ -69,7 +69,7 @@ namespace Orchard.Tests.Environment { Assert.That(accessor.GetContext(httpContext), Is.Null); - var scope = accessor.CreateContextScope(httpContext); + var scope = accessor.CreateWorkContextScope(httpContext); Assert.That(accessor.GetContext(httpContext), Is.Not.Null); scope.Dispose(); @@ -89,11 +89,11 @@ namespace Orchard.Tests.Environment { Assert.That(accessor1.GetContext(httpContext), Is.Null); Assert.That(accessor2.GetContext(httpContext), Is.Null); - var scope1 = accessor1.CreateContextScope(httpContext); + var scope1 = accessor1.CreateWorkContextScope(httpContext); Assert.That(accessor1.GetContext(httpContext), Is.Not.Null); Assert.That(accessor2.GetContext(httpContext), Is.Null); - var scope2 = accessor2.CreateContextScope(httpContext); + var scope2 = accessor2.CreateWorkContextScope(httpContext); Assert.That(accessor1.GetContext(httpContext), Is.Not.Null); Assert.That(accessor2.GetContext(httpContext), Is.Not.Null); @@ -120,7 +120,7 @@ namespace Orchard.Tests.Environment { Assert.That(accessor.GetContext(ambientHttpContext), Is.Null); Assert.That(accessor.GetContext(explicitHttpContext), Is.Null); - var scope = accessor.CreateContextScope(); + var scope = accessor.CreateWorkContextScope(); Assert.That(accessor.GetContext(), Is.Not.Null); Assert.That(accessor.GetContext(ambientHttpContext), Is.Not.Null); Assert.That(accessor.GetContext(explicitHttpContext), Is.Null); @@ -143,7 +143,7 @@ namespace Orchard.Tests.Environment { Assert.That(accessor.GetContext(), Is.Null); - var scope = accessor.CreateContextScope(); + var scope = accessor.CreateWorkContextScope(); Assert.That(accessor.GetContext(), Is.Not.Null); scope.Dispose(); @@ -161,11 +161,11 @@ namespace Orchard.Tests.Environment { Assert.That(accessor1.GetContext(), Is.Null); Assert.That(accessor2.GetContext(), Is.Null); - var scope1 = accessor1.CreateContextScope(); + var scope1 = accessor1.CreateWorkContextScope(); Assert.That(accessor1.GetContext(), Is.Not.Null); Assert.That(accessor2.GetContext(), Is.Null); - var scope2 = accessor2.CreateContextScope(); + var scope2 = accessor2.CreateWorkContextScope(); Assert.That(accessor1.GetContext(), Is.Not.Null); Assert.That(accessor2.GetContext(), Is.Not.Null); diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs index dbd37e585..0edc9c573 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs @@ -112,7 +112,8 @@ namespace Orchard.Setup.Services { // initialize database explicitly, and store shell descriptor var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint); - using ( var environment = new StandaloneEnvironment(bootstrapLifetimeScope) ) { + + using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) { // check if the database is already created (in case an exception occured in the second phase) var shellDescriptorRepository = environment.Resolve>(); diff --git a/src/Orchard/Commands/CommandHostAgent.cs b/src/Orchard/Commands/CommandHostAgent.cs index b32ff5bca..05799f2f1 100644 --- a/src/Orchard/Commands/CommandHostAgent.cs +++ b/src/Orchard/Commands/CommandHostAgent.cs @@ -128,7 +128,7 @@ namespace Orchard.Commands { } - private IStandaloneEnvironment CreateStandaloneEnvironment(string tenant) { + private IWorkContextScope CreateStandaloneEnvironment(string tenant) { var host = _hostContainer.Resolve(); var tenantManager = _hostContainer.Resolve(); diff --git a/src/Orchard/Environment/DefaultHostContainer.cs b/src/Orchard/Environment/DefaultHostContainer.cs index e7b9c6711..d546508ee 100644 --- a/src/Orchard/Environment/DefaultHostContainer.cs +++ b/src/Orchard/Environment/DefaultHostContainer.cs @@ -28,24 +28,14 @@ namespace Orchard.Environment { } bool TryResolve(string key, Type serviceType, out object value) { - // shared objects are resolved from the host first - // this is to ensure the lifecycle of components registered at the host level - // is consistent inside and outside of a containerproviderscope - return - TryResolveAtScope(_container, key, serviceType, out value) || - TryResolveAtScope(Scope.CurrentLifetimeScope, key, serviceType, out value); + return TryResolveAtScope(_container, key, serviceType, out value) ; } - object CreateInstance(Type t) { + static object CreateInstance(Type t) { if (t.IsAbstract || t.IsInterface) return null; - var instance = Activator.CreateInstance(t); - if (instance is IContextualizable) { - var effectiveContainer = Scope.CurrentLifetimeScope ?? _container; - (instance as IContextualizable).Hook(() => effectiveContainer.InjectUnsetProperties(instance)); - } - return instance; + return Activator.CreateInstance(t); } TService Resolve(Type serviceType, TService defaultValue = default(TService)) { @@ -111,53 +101,5 @@ namespace Orchard.Environment { } - public static IDisposable ContainerProviderScope(IContainerProvider containerProvider) { - return new Scope(containerProvider); - } - - class Scope : IDisposable { - private readonly IContainerProvider _containerProvider; - readonly Scope _prior; - - public Scope(IContainerProvider containerProvider) { - _containerProvider = containerProvider; - _prior = Current; - Current = this; - } - - public void Dispose() { - Current = _prior; - } - - public static ILifetimeScope CurrentLifetimeScope { - get { - var currentScope = Current; - if (currentScope != null && - currentScope._containerProvider != null) { - return currentScope._containerProvider.RequestLifetime; - } - return null; - } - } - - [ThreadStatic] - static Scope _fallback; - static readonly object _contextKey = new object(); - - static Scope Current { - get { - var context = HttpContext.Current; - return context != null ? (Scope)context.Items[_contextKey] : _fallback; - } - set { - var context = HttpContext.Current; - if (context != null) - context.Items[_contextKey] = value; - else { - _fallback = value; - } - } - } - } } } diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs index f5d6fd35e..6173b0e4d 100644 --- a/src/Orchard/Environment/DefaultOrchardHost.cs +++ b/src/Orchard/Environment/DefaultOrchardHost.cs @@ -14,6 +14,7 @@ using Orchard.Logging; using Orchard.Mvc; using Orchard.Mvc.ViewEngines; using Orchard.Utility.Extensions; +using Autofac; namespace Orchard.Environment { public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler { @@ -77,13 +78,13 @@ namespace Orchard.Environment { EndRequest(); } - IStandaloneEnvironment IOrchardHost.CreateStandaloneEnvironment(ShellSettings shellSettings) { + IWorkContextScope IOrchardHost.CreateStandaloneEnvironment(ShellSettings shellSettings) { Logger.Debug("Creating standalone environment for tenant {0}", shellSettings.Name); MonitorExtensions(); BuildCurrent(); var shellContext = CreateShellContext(shellSettings); - return new StandaloneEnvironment(shellContext.LifetimeScope); + return shellContext.LifetimeScope.CreateWorkContextScope(); } IEnumerable BuildCurrent() { diff --git a/src/Orchard/Environment/DefaultWorkContextAccessor.cs b/src/Orchard/Environment/DefaultWorkContextAccessor.cs index 6c0c13e7d..d3184c8ab 100644 --- a/src/Orchard/Environment/DefaultWorkContextAccessor.cs +++ b/src/Orchard/Environment/DefaultWorkContextAccessor.cs @@ -39,7 +39,7 @@ namespace Orchard.Environment { return _threadStaticContexts.TryGetValue(_workContextKey, out workContext) ? workContext : null; } - public IWorkContextScope CreateContextScope(HttpContextBase httpContext) { + public IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext) { var workLifetime = SpawnWorkLifetime(builder => { builder.Register(ctx => httpContext) @@ -56,10 +56,10 @@ namespace Orchard.Environment { } - public IWorkContextScope CreateContextScope() { + public IWorkContextScope CreateWorkContextScope() { var httpContext = _httpContextAccessor.Current(); if (httpContext != null) - return CreateContextScope(httpContext); + return CreateWorkContextScope(httpContext); var workLifetime = SpawnWorkLifetime(builder => { builder.Register(ctx => httpContext) @@ -116,6 +116,10 @@ namespace Orchard.Environment { public WorkContext WorkContext { get { return _workContext; } } + + public TService Resolve() { + return WorkContext.Service(); + } } class ThreadStaticScopeImplementation : IWorkContextScope { @@ -139,6 +143,10 @@ namespace Orchard.Environment { public WorkContext WorkContext { get { return _workContext; } } + + public TService Resolve() { + return WorkContext.Service(); + } } } diff --git a/src/Orchard/Environment/FiniteContainerProvider.cs b/src/Orchard/Environment/FiniteContainerProvider.cs deleted file mode 100644 index 5c21e5011..000000000 --- a/src/Orchard/Environment/FiniteContainerProvider.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Autofac; -using Autofac.Integration.Web; -using Orchard.Environment.AutofacUtil; - -namespace Orchard.Environment { - - class FiniteContainerProvider : IContainerProvider { - public FiniteContainerProvider(ILifetimeScope applicationContainer) { - ApplicationContainer = new LifetimeScopeContainer(applicationContainer); - RequestLifetime = ApplicationContainer.BeginLifetimeScope("httpRequest"); - } - - public void EndRequestLifetime() { - var disposeContainer = RequestLifetime; - RequestLifetime = null; - - if (disposeContainer != null) - disposeContainer.Dispose(); - } - - public IContainer ApplicationContainer { get; private set; } - - public ILifetimeScope RequestLifetime { get; private set; } - } -} \ No newline at end of file diff --git a/src/Orchard/Environment/IContextualizable.cs b/src/Orchard/Environment/IContextualizable.cs deleted file mode 100644 index 5d5ad7e4c..000000000 --- a/src/Orchard/Environment/IContextualizable.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System; - -namespace Orchard.Environment { - public interface IContextualizable { - void Hook(params Action[] contextualizers); - } -} \ No newline at end of file diff --git a/src/Orchard/Environment/IOrchardHost.cs b/src/Orchard/Environment/IOrchardHost.cs index d9ff03d91..99f58cbc5 100644 --- a/src/Orchard/Environment/IOrchardHost.cs +++ b/src/Orchard/Environment/IOrchardHost.cs @@ -28,6 +28,6 @@ namespace Orchard.Environment { /// Can be used to build an temporary self-contained instance of a shell's configured code. /// Services may be resolved from within this instance to configure and initialize it's storage. /// - IStandaloneEnvironment CreateStandaloneEnvironment(ShellSettings shellSettings); + IWorkContextScope CreateStandaloneEnvironment(ShellSettings shellSettings); } } diff --git a/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs b/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs index 64fe29fe7..9a3c8dd25 100644 --- a/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs +++ b/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs @@ -61,7 +61,7 @@ namespace Orchard.Environment.ShellBuilders { var shellScope = _shellContainerFactory.CreateContainer(settings, blueprint); ShellDescriptor currentDescriptor; - using (var standaloneEnvironment = new StandaloneEnvironment(shellScope)) { + using (var standaloneEnvironment = shellScope.CreateWorkContextScope()) { var shellDescriptorManager = standaloneEnvironment.Resolve(); currentDescriptor = shellDescriptorManager.GetShellDescriptor(); } diff --git a/src/Orchard/Environment/StandaloneEnvironment.cs b/src/Orchard/Environment/StandaloneEnvironment.cs deleted file mode 100644 index 02b8be364..000000000 --- a/src/Orchard/Environment/StandaloneEnvironment.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using Autofac; -using Autofac.Integration.Web; - -namespace Orchard.Environment { - public interface IStandaloneEnvironment : IDisposable { - TService Resolve(); - } - - public class StandaloneEnvironment : IStandaloneEnvironment { - private readonly IContainerProvider _containerProvider; - - public StandaloneEnvironment(ILifetimeScope applicationContainer) { - _containerProvider = new FiniteContainerProvider(applicationContainer); - } - - public TService Resolve() { - return _containerProvider.RequestLifetime.Resolve(); - } - - public void Dispose() { - _containerProvider.EndRequestLifetime(); - } - } -} \ No newline at end of file diff --git a/src/Orchard/Environment/State/DefaultProcessingEngine.cs b/src/Orchard/Environment/State/DefaultProcessingEngine.cs index 0504f0b6f..9e6e82784 100644 --- a/src/Orchard/Environment/State/DefaultProcessingEngine.cs +++ b/src/Orchard/Environment/State/DefaultProcessingEngine.cs @@ -68,7 +68,7 @@ namespace Orchard.Environment.State { private void Execute(Entry entry) { var shellContext = _shellContextFactory.CreateDescribedContext(entry.ShellSettings, entry.ShellDescriptor); using (shellContext.LifetimeScope) { - using (var standaloneEnvironment = new StandaloneEnvironment(shellContext.LifetimeScope)) { + using (var standaloneEnvironment = shellContext.LifetimeScope.CreateWorkContextScope()) { var eventBus = standaloneEnvironment.Resolve(); Logger.Information("Executing event {0} in process {1} for shell {2}", diff --git a/src/Orchard/IWorkContextAccessor.cs b/src/Orchard/IWorkContextAccessor.cs index f4e1bc166..eab5d8595 100644 --- a/src/Orchard/IWorkContextAccessor.cs +++ b/src/Orchard/IWorkContextAccessor.cs @@ -4,13 +4,14 @@ using System.Web; namespace Orchard { public interface IWorkContextAccessor : ISingletonDependency { WorkContext GetContext(HttpContextBase httpContext); - IWorkContextScope CreateContextScope(HttpContextBase httpContext); + IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext); WorkContext GetContext(); - IWorkContextScope CreateContextScope(); + IWorkContextScope CreateWorkContextScope(); } public interface IWorkContextScope : IDisposable { WorkContext WorkContext { get; } + TService Resolve(); } } diff --git a/src/Orchard/Localization/LocalizationUtilities.cs b/src/Orchard/Localization/LocalizationUtilities.cs index af33d069f..7de753aa9 100644 --- a/src/Orchard/Localization/LocalizationUtilities.cs +++ b/src/Orchard/Localization/LocalizationUtilities.cs @@ -5,8 +5,8 @@ using Orchard.Mvc; namespace Orchard.Localization { public class LocalizationUtilities { public static Localizer Resolve(ControllerContext controllerContext, string scope) { - var context = OrchardControllerFactory.GetRequestContainer(controllerContext.RouteData); - return context == null ? NullLocalizer.Instance : Resolve(context, scope); + var context = controllerContext.GetWorkContext(); + return context == null ? NullLocalizer.Instance : Resolve(context.Service(), scope); } public static Localizer Resolve(IComponentContext context, string scope) { diff --git a/src/Orchard/Mvc/Html/ContainerExtensions.cs b/src/Orchard/Mvc/Html/ContainerExtensions.cs index cf47a7d8e..167433e8c 100644 --- a/src/Orchard/Mvc/Html/ContainerExtensions.cs +++ b/src/Orchard/Mvc/Html/ContainerExtensions.cs @@ -11,11 +11,15 @@ namespace Orchard.Mvc.Html { /// /// himself public static TService Resolve(this HtmlHelper html) { - var containerProvider = html.ViewContext.RouteData.DataTokens["IContainerProvider"] as IContainerProvider; - if (containerProvider == null) + var workContextAccessor = html.ViewContext.RouteData.DataTokens["IWorkContextAccessor"] as IWorkContextAccessor; + if (workContextAccessor == null) throw new ApplicationException("Unable to resolve"); - return (containerProvider.RequestLifetime).Resolve(); + var workContext = workContextAccessor.GetContext(html.ViewContext.HttpContext); + if (workContext == null) + throw new ApplicationException("Unable to resolve"); + + return workContext.Service(); } } } \ No newline at end of file diff --git a/src/Orchard/Mvc/OrchardControllerFactory.cs b/src/Orchard/Mvc/OrchardControllerFactory.cs index 2e6846748..2f9a7c87f 100644 --- a/src/Orchard/Mvc/OrchardControllerFactory.cs +++ b/src/Orchard/Mvc/OrchardControllerFactory.cs @@ -6,7 +6,7 @@ using Autofac.Integration.Web; namespace Orchard.Mvc { public class OrchardControllerFactory : DefaultControllerFactory { - + public override IController CreateController(RequestContext requestContext, string controllerName) { var routeData = requestContext.RouteData; @@ -19,12 +19,14 @@ namespace Orchard.Mvc { // Now that the request container is known - try to resolve the controller object controller; 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, out controller)) { + // Locate the container this route is bound against + var workContextAccessor = GetWorkContextAccessor(routeData); + + var workContext = workContextAccessor != null ? workContextAccessor.GetContext(requestContext.HttpContext) : null; + + if (workContext != null && + workContext.Service().TryResolve(service, out controller)) { return (IController)controller; } @@ -54,14 +56,13 @@ namespace Orchard.Mvc { return GetAreaName(routeData.Route); } - public static ILifetimeScope GetRequestContainer(RouteData routeData) { + static IWorkContextAccessor GetWorkContextAccessor(RouteData routeData) { object dataTokenValue; if (routeData != null && routeData.DataTokens != null && - routeData.DataTokens.TryGetValue("IContainerProvider", out dataTokenValue) && - dataTokenValue is IContainerProvider) { - var containerProvider = (IContainerProvider) dataTokenValue; - return containerProvider.RequestLifetime; + routeData.DataTokens.TryGetValue("IWorkContextAccessor", out dataTokenValue) && + dataTokenValue is IWorkContextAccessor) { + return (IWorkContextAccessor)dataTokenValue; } return null; } diff --git a/src/Orchard/Mvc/Routes/ShellRoute.cs b/src/Orchard/Mvc/Routes/ShellRoute.cs index 17f8c29ef..de75583a6 100644 --- a/src/Orchard/Mvc/Routes/ShellRoute.cs +++ b/src/Orchard/Mvc/Routes/ShellRoute.cs @@ -14,15 +14,15 @@ namespace Orchard.Mvc.Routes { public class ShellRoute : RouteBase, IRouteWithArea { private readonly RouteBase _route; private readonly ShellSettings _shellSettings; - private readonly IContainer _container; + private readonly IWorkContextAccessor _workContextAccessor; private readonly IRunningShellTable _runningShellTable; - private UrlPrefix _urlPrefix; + private readonly UrlPrefix _urlPrefix; public ShellRoute(RouteBase route, ShellSettings shellSettings, ILifetimeScope shellLifetimeScope, IRunningShellTable runningShellTable) { _route = route; _shellSettings = shellSettings; _runningShellTable = runningShellTable; - _container = new LifetimeScopeContainer(shellLifetimeScope); + _workContextAccessor = shellLifetimeScope.Resolve(); if (!string.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) _urlPrefix = new UrlPrefix(_shellSettings.RequestUrlPrefix); @@ -56,10 +56,9 @@ namespace Orchard.Mvc.Routes { if (routeData == null) return null; - // otherwise paint wrap handler and return it - var containerProvider = new ContainerProvider(_container); - routeData.RouteHandler = new RouteHandler(containerProvider, routeData.RouteHandler); - routeData.DataTokens["IContainerProvider"] = containerProvider; + // otherwise wrap handler and return it + routeData.RouteHandler = new RouteHandler(_workContextAccessor, routeData.RouteHandler); + routeData.DataTokens["IWorkContextAccessor"] = _workContextAccessor; return routeData; } @@ -86,48 +85,30 @@ namespace Orchard.Mvc.Routes { return virtualPath; } - class ContainerProvider : IContainerProvider { - public ContainerProvider(IContainer applicationContainer) { - ApplicationContainer = applicationContainer; - } - - public void BeginRequestLifetime() { - RequestLifetime = ApplicationContainer.BeginLifetimeScope("httpRequest"); - } - - public void EndRequestLifetime() { - RequestLifetime.Dispose(); - RequestLifetime = null; - } - - public IContainer ApplicationContainer { get; set; } - public ILifetimeScope RequestLifetime { get; set; } - } - class RouteHandler : IRouteHandler { - private readonly ContainerProvider _containerProvider; + private readonly IWorkContextAccessor _workContextAccessor; private readonly IRouteHandler _routeHandler; - public RouteHandler(ContainerProvider containerProvider, IRouteHandler routeHandler) { - _containerProvider = containerProvider; + public RouteHandler(IWorkContextAccessor workContextAccessor, IRouteHandler routeHandler) { + _workContextAccessor = workContextAccessor; _routeHandler = routeHandler; } public IHttpHandler GetHttpHandler(RequestContext requestContext) { var httpHandler = _routeHandler.GetHttpHandler(requestContext); if (httpHandler is IHttpAsyncHandler) { - return new HttpAsyncHandler(_containerProvider, (IHttpAsyncHandler)httpHandler); + return new HttpAsyncHandler(_workContextAccessor, (IHttpAsyncHandler)httpHandler); } - return new HttpHandler(_containerProvider, httpHandler); + return new HttpHandler(_workContextAccessor, httpHandler); } } class HttpHandler : IHttpHandler, IRequiresSessionState, IHasRequestContext { - protected readonly ContainerProvider _containerProvider; + protected readonly IWorkContextAccessor _workContextAccessor; private readonly IHttpHandler _httpHandler; - public HttpHandler(ContainerProvider containerProvider, IHttpHandler httpHandler) { - _containerProvider = containerProvider; + public HttpHandler(IWorkContextAccessor workContextAccessor, IHttpHandler httpHandler) { + _workContextAccessor = workContextAccessor; _httpHandler = httpHandler; } @@ -136,14 +117,8 @@ namespace Orchard.Mvc.Routes { } public void ProcessRequest(HttpContext context) { - using (DefaultOrchardHostContainer.ContainerProviderScope(_containerProvider)) { - _containerProvider.BeginRequestLifetime(); - try { - _httpHandler.ProcessRequest(context); - } - finally { - _containerProvider.EndRequestLifetime(); - } + using (_workContextAccessor.CreateWorkContextScope(new HttpContextWrapper(context))) { + _httpHandler.ProcessRequest(context); } } @@ -159,19 +134,17 @@ namespace Orchard.Mvc.Routes { private readonly IHttpAsyncHandler _httpAsyncHandler; private IDisposable _scope; - public HttpAsyncHandler(ContainerProvider containerProvider, IHttpAsyncHandler httpAsyncHandler) + public HttpAsyncHandler(IWorkContextAccessor containerProvider, IHttpAsyncHandler httpAsyncHandler) : base(containerProvider, httpAsyncHandler) { _httpAsyncHandler = httpAsyncHandler; } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { - _scope = DefaultOrchardHostContainer.ContainerProviderScope(_containerProvider); - _containerProvider.BeginRequestLifetime(); + _scope = _workContextAccessor.CreateWorkContextScope(new HttpContextWrapper(context)); try { return _httpAsyncHandler.BeginProcessRequest(context, cb, extraData); } catch { - _containerProvider.EndRequestLifetime(); _scope.Dispose(); throw; } @@ -182,7 +155,6 @@ namespace Orchard.Mvc.Routes { _httpAsyncHandler.EndProcessRequest(result); } finally { - _containerProvider.EndRequestLifetime(); _scope.Dispose(); } } diff --git a/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs b/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs index c21f476ab..538a99968 100644 --- a/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs +++ b/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs @@ -16,7 +16,7 @@ using Orchard.Security.Permissions; namespace Orchard.Mvc.ViewEngines.Razor { - public abstract class WebViewPage : System.Web.Mvc.WebViewPage, IContextualizable { + public abstract class WebViewPage : System.Web.Mvc.WebViewPage { private object _display; private Localizer _localizer = NullLocalizer.Instance; private IEnumerable _contexturalizers = Enumerable.Empty(); @@ -31,8 +31,8 @@ namespace Orchard.Mvc.ViewEngines.Razor { public override void InitHelpers() { base.InitHelpers(); - foreach (var contextualize in _contexturalizers) - contextualize(); + var workContext = ViewContext.GetWorkContext(); + workContext.Service().InjectUnsetProperties(this); _localizer = LocalizationUtilities.Resolve(ViewContext, VirtualPath); _display = DisplayHelperFactory.CreateHelper(ViewContext, this); @@ -43,11 +43,6 @@ namespace Orchard.Mvc.ViewEngines.Razor { return Authorizer.Authorize(permission); } - void IContextualizable.Hook(params Action[] contextualizers) { - if (contextualizers != null && contextualizers.Any()) { - _contexturalizers = (_contexturalizers.Any()) ? _contexturalizers.Concat(contextualizers) : contextualizers; - } - } } public abstract class WebViewPage : WebViewPage { diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index d2020d883..7736ddf57 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -403,7 +403,6 @@ - @@ -613,7 +612,6 @@ - @@ -673,7 +671,6 @@ - diff --git a/src/Orchard/Tasks/SweepGenerator.cs b/src/Orchard/Tasks/SweepGenerator.cs index f811029b2..47c39a7e0 100644 --- a/src/Orchard/Tasks/SweepGenerator.cs +++ b/src/Orchard/Tasks/SweepGenerator.cs @@ -56,7 +56,7 @@ namespace Orchard.Tasks { public void DoWork() { // makes an inner container, similar to the per-request container - using (var standaloneEnvironment = new StandaloneEnvironment(_container)) { + using (var standaloneEnvironment = _container.CreateWorkContextScope()) { // resolve the manager and invoke it var manager = standaloneEnvironment.Resolve(); manager.Sweep(); diff --git a/src/Orchard/WorkContextExtensions.cs b/src/Orchard/WorkContextExtensions.cs index ea2c9589e..3b4956805 100644 --- a/src/Orchard/WorkContextExtensions.cs +++ b/src/Orchard/WorkContextExtensions.cs @@ -1,9 +1,45 @@ -using System.Web.Mvc; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; +using Autofac; namespace Orchard { public static class WorkContextExtensions { public static WorkContext GetContext(this IWorkContextAccessor workContextAccessor, ControllerContext controllerContext) { return workContextAccessor.GetContext(controllerContext.RequestContext.HttpContext); } + + public static WorkContext GetWorkContext(this RequestContext requestContext) { + if (requestContext == null) { + return null; + } + + var routeData = requestContext.RouteData; + object value; + if (routeData == null || + routeData.DataTokens == null || + !routeData.DataTokens.TryGetValue("IWorkContextAccessor", out value) || + !(value is IWorkContextAccessor)) { + return null; + } + + var workContextAccessor = (IWorkContextAccessor)value; + return workContextAccessor.GetContext(requestContext.HttpContext); + } + + public static WorkContext GetWorkContext(this ControllerContext controllerContext) { + if (controllerContext == null) { + return null; + } + return WorkContextExtensions.GetWorkContext(controllerContext.RequestContext); + } + + public static IWorkContextScope CreateWorkContextScope(this ILifetimeScope lifetimeScope, HttpContextBase httpContext) { + return lifetimeScope.Resolve().CreateWorkContextScope(httpContext); + } + + public static IWorkContextScope CreateWorkContextScope(this ILifetimeScope lifetimeScope) { + return lifetimeScope.Resolve().CreateWorkContextScope(); + } } }