Additional incremental work towards removing redundant layers.

--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-09-02 16:34:17 -07:00
parent 7e02c2a75f
commit 6a5536dd32
22 changed files with 117 additions and 216 deletions

View File

@@ -44,7 +44,7 @@ namespace Orchard.Specs.Hosting.Orchard.Web {
_host.ReloadExtensions(); _host.ReloadExtensions();
} }
public static IStandaloneEnvironment CreateStandaloneEnvironment(string name) { public static IWorkContextScope CreateStandaloneEnvironment(string name) {
var settings = _hostContainer.Resolve<IShellSettingsManager>().LoadSettings().SingleOrDefault(x => x.Name == name); var settings = _hostContainer.Resolve<IShellSettingsManager>().LoadSettings().SingleOrDefault(x => x.Name == name);
return Host.CreateStandaloneEnvironment(settings); return Host.CreateStandaloneEnvironment(settings);
} }

View File

@@ -37,7 +37,7 @@ namespace Orchard.Tests.Environment {
var accessor = _container.Resolve<IWorkContextAccessor>(); var accessor = _container.Resolve<IWorkContextAccessor>();
var httpContext = new StubHttpContext(); var httpContext = new StubHttpContext();
var workContextScope = accessor.CreateContextScope(httpContext); var workContextScope = accessor.CreateWorkContextScope(httpContext);
Assert.That(workContextScope.WorkContext, Is.Not.Null); Assert.That(workContextScope.WorkContext, Is.Not.Null);
var workContext = accessor.GetContext(httpContext); var workContext = accessor.GetContext(httpContext);
@@ -48,11 +48,11 @@ namespace Orchard.Tests.Environment {
public void DifferentHttpContextWillHoldDifferentWorkContext() { public void DifferentHttpContextWillHoldDifferentWorkContext() {
var accessor = _container.Resolve<IWorkContextAccessor>(); var accessor = _container.Resolve<IWorkContextAccessor>();
var httpContext1 = new StubHttpContext(); var httpContext1 = new StubHttpContext();
var workContextScope1 = accessor.CreateContextScope(httpContext1); var workContextScope1 = accessor.CreateWorkContextScope(httpContext1);
var workContext1 = accessor.GetContext(httpContext1); var workContext1 = accessor.GetContext(httpContext1);
var httpContext2 = new StubHttpContext(); var httpContext2 = new StubHttpContext();
var workContextScope2 = accessor.CreateContextScope(httpContext2); var workContextScope2 = accessor.CreateWorkContextScope(httpContext2);
var workContext2 = accessor.GetContext(httpContext2); var workContext2 = accessor.GetContext(httpContext2);
Assert.That(workContext1, Is.Not.Null); Assert.That(workContext1, Is.Not.Null);
@@ -69,7 +69,7 @@ namespace Orchard.Tests.Environment {
Assert.That(accessor.GetContext(httpContext), Is.Null); 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); Assert.That(accessor.GetContext(httpContext), Is.Not.Null);
scope.Dispose(); scope.Dispose();
@@ -89,11 +89,11 @@ namespace Orchard.Tests.Environment {
Assert.That(accessor1.GetContext(httpContext), Is.Null); Assert.That(accessor1.GetContext(httpContext), Is.Null);
Assert.That(accessor2.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(accessor1.GetContext(httpContext), Is.Not.Null);
Assert.That(accessor2.GetContext(httpContext), Is.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(accessor1.GetContext(httpContext), Is.Not.Null);
Assert.That(accessor2.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(ambientHttpContext), Is.Null);
Assert.That(accessor.GetContext(explicitHttpContext), 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(), Is.Not.Null);
Assert.That(accessor.GetContext(ambientHttpContext), Is.Not.Null); Assert.That(accessor.GetContext(ambientHttpContext), Is.Not.Null);
Assert.That(accessor.GetContext(explicitHttpContext), Is.Null); Assert.That(accessor.GetContext(explicitHttpContext), Is.Null);
@@ -143,7 +143,7 @@ namespace Orchard.Tests.Environment {
Assert.That(accessor.GetContext(), Is.Null); Assert.That(accessor.GetContext(), Is.Null);
var scope = accessor.CreateContextScope(); var scope = accessor.CreateWorkContextScope();
Assert.That(accessor.GetContext(), Is.Not.Null); Assert.That(accessor.GetContext(), Is.Not.Null);
scope.Dispose(); scope.Dispose();
@@ -161,11 +161,11 @@ namespace Orchard.Tests.Environment {
Assert.That(accessor1.GetContext(), Is.Null); Assert.That(accessor1.GetContext(), Is.Null);
Assert.That(accessor2.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(accessor1.GetContext(), Is.Not.Null);
Assert.That(accessor2.GetContext(), Is.Null); Assert.That(accessor2.GetContext(), Is.Null);
var scope2 = accessor2.CreateContextScope(); var scope2 = accessor2.CreateWorkContextScope();
Assert.That(accessor1.GetContext(), Is.Not.Null); Assert.That(accessor1.GetContext(), Is.Not.Null);
Assert.That(accessor2.GetContext(), Is.Not.Null); Assert.That(accessor2.GetContext(), Is.Not.Null);

View File

@@ -112,7 +112,8 @@ namespace Orchard.Setup.Services {
// initialize database explicitly, and store shell descriptor // initialize database explicitly, and store shell descriptor
var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint); 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) // check if the database is already created (in case an exception occured in the second phase)
var shellDescriptorRepository = environment.Resolve<IRepository<ShellDescriptorRecord>>(); var shellDescriptorRepository = environment.Resolve<IRepository<ShellDescriptorRecord>>();

View File

@@ -128,7 +128,7 @@ namespace Orchard.Commands {
} }
private IStandaloneEnvironment CreateStandaloneEnvironment(string tenant) { private IWorkContextScope CreateStandaloneEnvironment(string tenant) {
var host = _hostContainer.Resolve<IOrchardHost>(); var host = _hostContainer.Resolve<IOrchardHost>();
var tenantManager = _hostContainer.Resolve<IShellSettingsManager>(); var tenantManager = _hostContainer.Resolve<IShellSettingsManager>();

View File

@@ -28,24 +28,14 @@ namespace Orchard.Environment {
} }
bool TryResolve(string key, Type serviceType, out object value) { bool TryResolve(string key, Type serviceType, out object value) {
// shared objects are resolved from the host first return TryResolveAtScope(_container, key, serviceType, out value) ;
// 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);
} }
object CreateInstance(Type t) { static object CreateInstance(Type t) {
if (t.IsAbstract || t.IsInterface) if (t.IsAbstract || t.IsInterface)
return null; return null;
var instance = Activator.CreateInstance(t); return Activator.CreateInstance(t);
if (instance is IContextualizable) {
var effectiveContainer = Scope.CurrentLifetimeScope ?? _container;
(instance as IContextualizable).Hook(() => effectiveContainer.InjectUnsetProperties(instance));
}
return instance;
} }
TService Resolve<TService>(Type serviceType, TService defaultValue = default(TService)) { TService Resolve<TService>(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;
}
}
}
}
} }
} }

View File

@@ -14,6 +14,7 @@ using Orchard.Logging;
using Orchard.Mvc; using Orchard.Mvc;
using Orchard.Mvc.ViewEngines; using Orchard.Mvc.ViewEngines;
using Orchard.Utility.Extensions; using Orchard.Utility.Extensions;
using Autofac;
namespace Orchard.Environment { namespace Orchard.Environment {
public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler { public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler {
@@ -77,13 +78,13 @@ namespace Orchard.Environment {
EndRequest(); EndRequest();
} }
IStandaloneEnvironment IOrchardHost.CreateStandaloneEnvironment(ShellSettings shellSettings) { IWorkContextScope IOrchardHost.CreateStandaloneEnvironment(ShellSettings shellSettings) {
Logger.Debug("Creating standalone environment for tenant {0}", shellSettings.Name); Logger.Debug("Creating standalone environment for tenant {0}", shellSettings.Name);
MonitorExtensions(); MonitorExtensions();
BuildCurrent(); BuildCurrent();
var shellContext = CreateShellContext(shellSettings); var shellContext = CreateShellContext(shellSettings);
return new StandaloneEnvironment(shellContext.LifetimeScope); return shellContext.LifetimeScope.CreateWorkContextScope();
} }
IEnumerable<ShellContext> BuildCurrent() { IEnumerable<ShellContext> BuildCurrent() {

View File

@@ -39,7 +39,7 @@ namespace Orchard.Environment {
return _threadStaticContexts.TryGetValue(_workContextKey, out workContext) ? workContext : null; return _threadStaticContexts.TryGetValue(_workContextKey, out workContext) ? workContext : null;
} }
public IWorkContextScope CreateContextScope(HttpContextBase httpContext) { public IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext) {
var workLifetime = SpawnWorkLifetime(builder => { var workLifetime = SpawnWorkLifetime(builder => {
builder.Register(ctx => httpContext) builder.Register(ctx => httpContext)
@@ -56,10 +56,10 @@ namespace Orchard.Environment {
} }
public IWorkContextScope CreateContextScope() { public IWorkContextScope CreateWorkContextScope() {
var httpContext = _httpContextAccessor.Current(); var httpContext = _httpContextAccessor.Current();
if (httpContext != null) if (httpContext != null)
return CreateContextScope(httpContext); return CreateWorkContextScope(httpContext);
var workLifetime = SpawnWorkLifetime(builder => { var workLifetime = SpawnWorkLifetime(builder => {
builder.Register(ctx => httpContext) builder.Register(ctx => httpContext)
@@ -116,6 +116,10 @@ namespace Orchard.Environment {
public WorkContext WorkContext { public WorkContext WorkContext {
get { return _workContext; } get { return _workContext; }
} }
public TService Resolve<TService>() {
return WorkContext.Service<TService>();
}
} }
class ThreadStaticScopeImplementation : IWorkContextScope { class ThreadStaticScopeImplementation : IWorkContextScope {
@@ -139,6 +143,10 @@ namespace Orchard.Environment {
public WorkContext WorkContext { public WorkContext WorkContext {
get { return _workContext; } get { return _workContext; }
} }
public TService Resolve<TService>() {
return WorkContext.Service<TService>();
}
} }
} }

View File

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

View File

@@ -1,7 +0,0 @@
using System;
namespace Orchard.Environment {
public interface IContextualizable {
void Hook(params Action[] contextualizers);
}
}

View File

@@ -28,6 +28,6 @@ namespace Orchard.Environment {
/// Can be used to build an temporary self-contained instance of a shell's configured code. /// 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. /// Services may be resolved from within this instance to configure and initialize it's storage.
/// </summary> /// </summary>
IStandaloneEnvironment CreateStandaloneEnvironment(ShellSettings shellSettings); IWorkContextScope CreateStandaloneEnvironment(ShellSettings shellSettings);
} }
} }

View File

@@ -61,7 +61,7 @@ namespace Orchard.Environment.ShellBuilders {
var shellScope = _shellContainerFactory.CreateContainer(settings, blueprint); var shellScope = _shellContainerFactory.CreateContainer(settings, blueprint);
ShellDescriptor currentDescriptor; ShellDescriptor currentDescriptor;
using (var standaloneEnvironment = new StandaloneEnvironment(shellScope)) { using (var standaloneEnvironment = shellScope.CreateWorkContextScope()) {
var shellDescriptorManager = standaloneEnvironment.Resolve<IShellDescriptorManager>(); var shellDescriptorManager = standaloneEnvironment.Resolve<IShellDescriptorManager>();
currentDescriptor = shellDescriptorManager.GetShellDescriptor(); currentDescriptor = shellDescriptorManager.GetShellDescriptor();
} }

View File

@@ -1,25 +0,0 @@
using System;
using Autofac;
using Autofac.Integration.Web;
namespace Orchard.Environment {
public interface IStandaloneEnvironment : IDisposable {
TService Resolve<TService>();
}
public class StandaloneEnvironment : IStandaloneEnvironment {
private readonly IContainerProvider _containerProvider;
public StandaloneEnvironment(ILifetimeScope applicationContainer) {
_containerProvider = new FiniteContainerProvider(applicationContainer);
}
public TService Resolve<TService>() {
return _containerProvider.RequestLifetime.Resolve<TService>();
}
public void Dispose() {
_containerProvider.EndRequestLifetime();
}
}
}

View File

@@ -68,7 +68,7 @@ namespace Orchard.Environment.State {
private void Execute(Entry entry) { private void Execute(Entry entry) {
var shellContext = _shellContextFactory.CreateDescribedContext(entry.ShellSettings, entry.ShellDescriptor); var shellContext = _shellContextFactory.CreateDescribedContext(entry.ShellSettings, entry.ShellDescriptor);
using (shellContext.LifetimeScope) { using (shellContext.LifetimeScope) {
using (var standaloneEnvironment = new StandaloneEnvironment(shellContext.LifetimeScope)) { using (var standaloneEnvironment = shellContext.LifetimeScope.CreateWorkContextScope()) {
var eventBus = standaloneEnvironment.Resolve<IEventBus>(); var eventBus = standaloneEnvironment.Resolve<IEventBus>();
Logger.Information("Executing event {0} in process {1} for shell {2}", Logger.Information("Executing event {0} in process {1} for shell {2}",

View File

@@ -4,13 +4,14 @@ using System.Web;
namespace Orchard { namespace Orchard {
public interface IWorkContextAccessor : ISingletonDependency { public interface IWorkContextAccessor : ISingletonDependency {
WorkContext GetContext(HttpContextBase httpContext); WorkContext GetContext(HttpContextBase httpContext);
IWorkContextScope CreateContextScope(HttpContextBase httpContext); IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext);
WorkContext GetContext(); WorkContext GetContext();
IWorkContextScope CreateContextScope(); IWorkContextScope CreateWorkContextScope();
} }
public interface IWorkContextScope : IDisposable { public interface IWorkContextScope : IDisposable {
WorkContext WorkContext { get; } WorkContext WorkContext { get; }
TService Resolve<TService>();
} }
} }

View File

@@ -5,8 +5,8 @@ using Orchard.Mvc;
namespace Orchard.Localization { namespace Orchard.Localization {
public class LocalizationUtilities { public class LocalizationUtilities {
public static Localizer Resolve(ControllerContext controllerContext, string scope) { public static Localizer Resolve(ControllerContext controllerContext, string scope) {
var context = OrchardControllerFactory.GetRequestContainer(controllerContext.RouteData); var context = controllerContext.GetWorkContext();
return context == null ? NullLocalizer.Instance : Resolve(context, scope); return context == null ? NullLocalizer.Instance : Resolve(context.Service<ILifetimeScope>(), scope);
} }
public static Localizer Resolve(IComponentContext context, string scope) { public static Localizer Resolve(IComponentContext context, string scope) {

View File

@@ -11,11 +11,15 @@ namespace Orchard.Mvc.Html {
/// <see cref="http://en.wikipedia.org/wiki/Harry_Houdini"/> /// <see cref="http://en.wikipedia.org/wiki/Harry_Houdini"/>
/// <returns>himself</returns> /// <returns>himself</returns>
public static TService Resolve<TService>(this HtmlHelper html) { public static TService Resolve<TService>(this HtmlHelper html) {
var containerProvider = html.ViewContext.RouteData.DataTokens["IContainerProvider"] as IContainerProvider; var workContextAccessor = html.ViewContext.RouteData.DataTokens["IWorkContextAccessor"] as IWorkContextAccessor;
if (containerProvider == null) if (workContextAccessor == null)
throw new ApplicationException("Unable to resolve"); throw new ApplicationException("Unable to resolve");
return (containerProvider.RequestLifetime).Resolve<TService>(); var workContext = workContextAccessor.GetContext(html.ViewContext.HttpContext);
if (workContext == null)
throw new ApplicationException("Unable to resolve");
return workContext.Service<TService>();
} }
} }
} }

View File

@@ -6,7 +6,7 @@ using Autofac.Integration.Web;
namespace Orchard.Mvc { namespace Orchard.Mvc {
public class OrchardControllerFactory : DefaultControllerFactory { public class OrchardControllerFactory : DefaultControllerFactory {
public override IController CreateController(RequestContext requestContext, string controllerName) { public override IController CreateController(RequestContext requestContext, string controllerName) {
var routeData = requestContext.RouteData; var routeData = requestContext.RouteData;
@@ -19,12 +19,14 @@ namespace Orchard.Mvc {
// Now that the request container is known - try to resolve the controller // Now that the request container is known - try to resolve the controller
object controller; object controller;
var service = new KeyedService(serviceKey, typeof(IController)); var service = new KeyedService(serviceKey, typeof(IController));
// Locate the container this route is bound against
var container = GetRequestContainer(routeData);
if (container != null && // Locate the container this route is bound against
container.TryResolve(service, out controller)) { var workContextAccessor = GetWorkContextAccessor(routeData);
var workContext = workContextAccessor != null ? workContextAccessor.GetContext(requestContext.HttpContext) : null;
if (workContext != null &&
workContext.Service<ILifetimeScope>().TryResolve(service, out controller)) {
return (IController)controller; return (IController)controller;
} }
@@ -54,14 +56,13 @@ namespace Orchard.Mvc {
return GetAreaName(routeData.Route); return GetAreaName(routeData.Route);
} }
public static ILifetimeScope GetRequestContainer(RouteData routeData) { static IWorkContextAccessor GetWorkContextAccessor(RouteData routeData) {
object dataTokenValue; object dataTokenValue;
if (routeData != null && if (routeData != null &&
routeData.DataTokens != null && routeData.DataTokens != null &&
routeData.DataTokens.TryGetValue("IContainerProvider", out dataTokenValue) && routeData.DataTokens.TryGetValue("IWorkContextAccessor", out dataTokenValue) &&
dataTokenValue is IContainerProvider) { dataTokenValue is IWorkContextAccessor) {
var containerProvider = (IContainerProvider) dataTokenValue; return (IWorkContextAccessor)dataTokenValue;
return containerProvider.RequestLifetime;
} }
return null; return null;
} }

View File

@@ -14,15 +14,15 @@ namespace Orchard.Mvc.Routes {
public class ShellRoute : RouteBase, IRouteWithArea { public class ShellRoute : RouteBase, IRouteWithArea {
private readonly RouteBase _route; private readonly RouteBase _route;
private readonly ShellSettings _shellSettings; private readonly ShellSettings _shellSettings;
private readonly IContainer _container; private readonly IWorkContextAccessor _workContextAccessor;
private readonly IRunningShellTable _runningShellTable; private readonly IRunningShellTable _runningShellTable;
private UrlPrefix _urlPrefix; private readonly UrlPrefix _urlPrefix;
public ShellRoute(RouteBase route, ShellSettings shellSettings, ILifetimeScope shellLifetimeScope, IRunningShellTable runningShellTable) { public ShellRoute(RouteBase route, ShellSettings shellSettings, ILifetimeScope shellLifetimeScope, IRunningShellTable runningShellTable) {
_route = route; _route = route;
_shellSettings = shellSettings; _shellSettings = shellSettings;
_runningShellTable = runningShellTable; _runningShellTable = runningShellTable;
_container = new LifetimeScopeContainer(shellLifetimeScope); _workContextAccessor = shellLifetimeScope.Resolve<IWorkContextAccessor>();
if (!string.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) if (!string.IsNullOrEmpty(_shellSettings.RequestUrlPrefix))
_urlPrefix = new UrlPrefix(_shellSettings.RequestUrlPrefix); _urlPrefix = new UrlPrefix(_shellSettings.RequestUrlPrefix);
@@ -56,10 +56,9 @@ namespace Orchard.Mvc.Routes {
if (routeData == null) if (routeData == null)
return null; return null;
// otherwise paint wrap handler and return it // otherwise wrap handler and return it
var containerProvider = new ContainerProvider(_container); routeData.RouteHandler = new RouteHandler(_workContextAccessor, routeData.RouteHandler);
routeData.RouteHandler = new RouteHandler(containerProvider, routeData.RouteHandler); routeData.DataTokens["IWorkContextAccessor"] = _workContextAccessor;
routeData.DataTokens["IContainerProvider"] = containerProvider;
return routeData; return routeData;
} }
@@ -86,48 +85,30 @@ namespace Orchard.Mvc.Routes {
return virtualPath; 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 { class RouteHandler : IRouteHandler {
private readonly ContainerProvider _containerProvider; private readonly IWorkContextAccessor _workContextAccessor;
private readonly IRouteHandler _routeHandler; private readonly IRouteHandler _routeHandler;
public RouteHandler(ContainerProvider containerProvider, IRouteHandler routeHandler) { public RouteHandler(IWorkContextAccessor workContextAccessor, IRouteHandler routeHandler) {
_containerProvider = containerProvider; _workContextAccessor = workContextAccessor;
_routeHandler = routeHandler; _routeHandler = routeHandler;
} }
public IHttpHandler GetHttpHandler(RequestContext requestContext) { public IHttpHandler GetHttpHandler(RequestContext requestContext) {
var httpHandler = _routeHandler.GetHttpHandler(requestContext); var httpHandler = _routeHandler.GetHttpHandler(requestContext);
if (httpHandler is IHttpAsyncHandler) { 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 { class HttpHandler : IHttpHandler, IRequiresSessionState, IHasRequestContext {
protected readonly ContainerProvider _containerProvider; protected readonly IWorkContextAccessor _workContextAccessor;
private readonly IHttpHandler _httpHandler; private readonly IHttpHandler _httpHandler;
public HttpHandler(ContainerProvider containerProvider, IHttpHandler httpHandler) { public HttpHandler(IWorkContextAccessor workContextAccessor, IHttpHandler httpHandler) {
_containerProvider = containerProvider; _workContextAccessor = workContextAccessor;
_httpHandler = httpHandler; _httpHandler = httpHandler;
} }
@@ -136,14 +117,8 @@ namespace Orchard.Mvc.Routes {
} }
public void ProcessRequest(HttpContext context) { public void ProcessRequest(HttpContext context) {
using (DefaultOrchardHostContainer.ContainerProviderScope(_containerProvider)) { using (_workContextAccessor.CreateWorkContextScope(new HttpContextWrapper(context))) {
_containerProvider.BeginRequestLifetime(); _httpHandler.ProcessRequest(context);
try {
_httpHandler.ProcessRequest(context);
}
finally {
_containerProvider.EndRequestLifetime();
}
} }
} }
@@ -159,19 +134,17 @@ namespace Orchard.Mvc.Routes {
private readonly IHttpAsyncHandler _httpAsyncHandler; private readonly IHttpAsyncHandler _httpAsyncHandler;
private IDisposable _scope; private IDisposable _scope;
public HttpAsyncHandler(ContainerProvider containerProvider, IHttpAsyncHandler httpAsyncHandler) public HttpAsyncHandler(IWorkContextAccessor containerProvider, IHttpAsyncHandler httpAsyncHandler)
: base(containerProvider, httpAsyncHandler) { : base(containerProvider, httpAsyncHandler) {
_httpAsyncHandler = httpAsyncHandler; _httpAsyncHandler = httpAsyncHandler;
} }
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {
_scope = DefaultOrchardHostContainer.ContainerProviderScope(_containerProvider); _scope = _workContextAccessor.CreateWorkContextScope(new HttpContextWrapper(context));
_containerProvider.BeginRequestLifetime();
try { try {
return _httpAsyncHandler.BeginProcessRequest(context, cb, extraData); return _httpAsyncHandler.BeginProcessRequest(context, cb, extraData);
} }
catch { catch {
_containerProvider.EndRequestLifetime();
_scope.Dispose(); _scope.Dispose();
throw; throw;
} }
@@ -182,7 +155,6 @@ namespace Orchard.Mvc.Routes {
_httpAsyncHandler.EndProcessRequest(result); _httpAsyncHandler.EndProcessRequest(result);
} }
finally { finally {
_containerProvider.EndRequestLifetime();
_scope.Dispose(); _scope.Dispose();
} }
} }

View File

@@ -16,7 +16,7 @@ using Orchard.Security.Permissions;
namespace Orchard.Mvc.ViewEngines.Razor { namespace Orchard.Mvc.ViewEngines.Razor {
public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>, IContextualizable { public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel> {
private object _display; private object _display;
private Localizer _localizer = NullLocalizer.Instance; private Localizer _localizer = NullLocalizer.Instance;
private IEnumerable<Action> _contexturalizers = Enumerable.Empty<Action>(); private IEnumerable<Action> _contexturalizers = Enumerable.Empty<Action>();
@@ -31,8 +31,8 @@ namespace Orchard.Mvc.ViewEngines.Razor {
public override void InitHelpers() { public override void InitHelpers() {
base.InitHelpers(); base.InitHelpers();
foreach (var contextualize in _contexturalizers) var workContext = ViewContext.GetWorkContext();
contextualize(); workContext.Service<IContainer>().InjectUnsetProperties(this);
_localizer = LocalizationUtilities.Resolve(ViewContext, VirtualPath); _localizer = LocalizationUtilities.Resolve(ViewContext, VirtualPath);
_display = DisplayHelperFactory.CreateHelper(ViewContext, this); _display = DisplayHelperFactory.CreateHelper(ViewContext, this);
@@ -43,11 +43,6 @@ namespace Orchard.Mvc.ViewEngines.Razor {
return Authorizer.Authorize(permission); 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<object> { public abstract class WebViewPage : WebViewPage<object> {

View File

@@ -403,7 +403,6 @@
<Compile Include="DisplayManagement\Implementation\ShapeHelper.cs" /> <Compile Include="DisplayManagement\Implementation\ShapeHelper.cs" />
<Compile Include="DisplayManagement\Implementation\ShapeHelperFactory.cs" /> <Compile Include="DisplayManagement\Implementation\ShapeHelperFactory.cs" />
<Compile Include="Environment\DefaultWorkContextAccessor.cs" /> <Compile Include="Environment\DefaultWorkContextAccessor.cs" />
<Compile Include="Environment\IContextualizable.cs" />
<Compile Include="Environment\IHostLocalRestart.cs" /> <Compile Include="Environment\IHostLocalRestart.cs" />
<Compile Include="Environment\IShellContainerRegistrations.cs" /> <Compile Include="Environment\IShellContainerRegistrations.cs" />
<Compile Include="FileSystems\Dependencies\DynamicModuleVirtualPathProvider.cs" /> <Compile Include="FileSystems\Dependencies\DynamicModuleVirtualPathProvider.cs" />
@@ -613,7 +612,6 @@
<Compile Include="Environment\Descriptor\Models\ShellDescriptor.cs" /> <Compile Include="Environment\Descriptor\Models\ShellDescriptor.cs" />
<Compile Include="Environment\ShellBuilders\ShellContainerFactory.cs" /> <Compile Include="Environment\ShellBuilders\ShellContainerFactory.cs" />
<Compile Include="Environment\Configuration\ShellSettings.cs" /> <Compile Include="Environment\Configuration\ShellSettings.cs" />
<Compile Include="Environment\StandaloneEnvironment.cs" />
<Compile Include="Events\DefaultOrchardEventBus.cs" /> <Compile Include="Events\DefaultOrchardEventBus.cs" />
<Compile Include="Events\EventsInterceptor.cs" /> <Compile Include="Events\EventsInterceptor.cs" />
<Compile Include="Events\EventsModule.cs" /> <Compile Include="Events\EventsModule.cs" />
@@ -673,7 +671,6 @@
<Compile Include="Mvc\Html\FileRegistrationContext.cs" /> <Compile Include="Mvc\Html\FileRegistrationContext.cs" />
<Compile Include="Mvc\Html\MvcFormAntiForgeryPost.cs" /> <Compile Include="Mvc\Html\MvcFormAntiForgeryPost.cs" />
<Compile Include="Mvc\Html\SiteServiceExtensions.cs" /> <Compile Include="Mvc\Html\SiteServiceExtensions.cs" />
<Compile Include="Environment\FiniteContainerProvider.cs" />
<Compile Include="Tasks\Scheduling\IScheduledTaskHandler.cs" /> <Compile Include="Tasks\Scheduling\IScheduledTaskHandler.cs" />
<Compile Include="Tasks\Scheduling\IScheduledTaskManager.cs" /> <Compile Include="Tasks\Scheduling\IScheduledTaskManager.cs" />
<Compile Include="Tasks\Scheduling\ScheduledTaskContext.cs" /> <Compile Include="Tasks\Scheduling\ScheduledTaskContext.cs" />

View File

@@ -56,7 +56,7 @@ namespace Orchard.Tasks {
public void DoWork() { public void DoWork() {
// makes an inner container, similar to the per-request container // 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 // resolve the manager and invoke it
var manager = standaloneEnvironment.Resolve<IBackgroundService>(); var manager = standaloneEnvironment.Resolve<IBackgroundService>();
manager.Sweep(); manager.Sweep();

View File

@@ -1,9 +1,45 @@
using System.Web.Mvc; using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
namespace Orchard { namespace Orchard {
public static class WorkContextExtensions { public static class WorkContextExtensions {
public static WorkContext GetContext(this IWorkContextAccessor workContextAccessor, ControllerContext controllerContext) { public static WorkContext GetContext(this IWorkContextAccessor workContextAccessor, ControllerContext controllerContext) {
return workContextAccessor.GetContext(controllerContext.RequestContext.HttpContext); 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<IWorkContextAccessor>().CreateWorkContextScope(httpContext);
}
public static IWorkContextScope CreateWorkContextScope(this ILifetimeScope lifetimeScope) {
return lifetimeScope.Resolve<IWorkContextAccessor>().CreateWorkContextScope();
}
} }
} }