mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Additional incremental work towards removing redundant layers.
--HG-- branch : dev
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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>>();
|
||||||
|
@@ -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>();
|
||||||
|
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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() {
|
||||||
|
@@ -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>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Orchard.Environment {
|
|
||||||
public interface IContextualizable {
|
|
||||||
void Hook(params Action[] contextualizers);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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}",
|
||||||
|
@@ -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>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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> {
|
||||||
|
@@ -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" />
|
||||||
|
@@ -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();
|
||||||
|
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user