diff --git a/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs b/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs index 62493aaab..c696c8b75 100644 --- a/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs +++ b/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs @@ -46,7 +46,7 @@ namespace Orchard.Core.Tests.Routable.Services { builder.RegisterInstance(new Mock().Object); builder.RegisterInstance(new Mock().Object); builder.RegisterType().As(); - builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs b/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs index 8edd2de91..5de77cf97 100644 --- a/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs +++ b/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs @@ -22,7 +22,7 @@ namespace Orchard.Tests.Environment { } protected override void Register(ContainerBuilder builder) { - builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterAutoMocking(); } diff --git a/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs b/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs index 56a96df61..4857f4b72 100644 --- a/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs +++ b/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs @@ -21,7 +21,7 @@ namespace Orchard.Tests.Environment.ShellBuilders { public void Init() { var builder = new ContainerBuilder(); builder.RegisterType().As(); - builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterAutoMocking(Moq.MockBehavior.Strict); _container = builder.Build(); } diff --git a/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs b/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs index e35a2f401..d564bb24c 100644 --- a/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs +++ b/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs @@ -23,7 +23,7 @@ namespace Orchard.Tests.Environment.State { public void Init() { var builder = new ContainerBuilder(); builder.RegisterType().As(); - builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterAutoMocking(); _container = builder.Build(); diff --git a/src/Orchard.Tests/Localization/CultureManagerTests.cs b/src/Orchard.Tests/Localization/CultureManagerTests.cs index 9d202c2d0..4a0d9e1ce 100644 --- a/src/Orchard.Tests/Localization/CultureManagerTests.cs +++ b/src/Orchard.Tests/Localization/CultureManagerTests.cs @@ -51,7 +51,7 @@ namespace Orchard.Tests.Localization { builder.RegisterInstance(new Mock().Object); builder.RegisterInstance(new Mock().Object); builder.RegisterType().As(); - builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs b/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs index 80a99f72f..33bbfb968 100644 --- a/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs +++ b/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs @@ -36,7 +36,7 @@ namespace Orchard.Tests.Mvc.Routes { rootBuilder.Register(ctx => _routes); rootBuilder.RegisterType().InstancePerDependency(); rootBuilder.RegisterType().As().SingleInstance(); - rootBuilder.RegisterType().As().InstancePerMatchingLifetimeScope("shell"); + rootBuilder.RegisterType().As().InstancePerMatchingLifetimeScope("shell"); rootBuilder.RegisterType().As(); _rootContainer = rootBuilder.Build(); diff --git a/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs b/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs index 9e0469631..9bb99fa08 100644 --- a/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs +++ b/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs @@ -12,7 +12,7 @@ namespace Orchard.Tests.Tasks { public class SweepGeneratorTests : ContainerTestBase { protected override void Register(ContainerBuilder builder) { builder.RegisterAutoMocking(MockBehavior.Loose); - builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType(); } diff --git a/src/Orchard.Tests/UI/ShapeTests.cs b/src/Orchard.Tests/UI/ShapeTests.cs index f5d8fb4c0..efac540ea 100644 --- a/src/Orchard.Tests/UI/ShapeTests.cs +++ b/src/Orchard.Tests/UI/ShapeTests.cs @@ -19,7 +19,7 @@ namespace Orchard.Tests.UI { protected override void Register(ContainerBuilder builder) { builder.RegisterType().As(); - builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs index bd77e21af..f7f185abb 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs @@ -45,6 +45,8 @@ namespace Orchard.Setup { // standard services needed in setup mode builder.RegisterModule(new MvcModule()); builder.RegisterModule(new CommandModule()); + builder.RegisterModule(new WorkContextModule()); + builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().As().InstancePerLifetimeScope(); @@ -58,7 +60,7 @@ namespace Orchard.Setup { builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerMatchingLifetimeScope("shell"); + builder.RegisterType().As().InstancePerMatchingLifetimeScope("shell"); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); diff --git a/src/Orchard/Environment/DefaultWorkContextAccessor.cs b/src/Orchard/Environment/WorkContextAccessor.cs similarity index 60% rename from src/Orchard/Environment/DefaultWorkContextAccessor.cs rename to src/Orchard/Environment/WorkContextAccessor.cs index 9a2c6816f..307ed2dd2 100644 --- a/src/Orchard/Environment/DefaultWorkContextAccessor.cs +++ b/src/Orchard/Environment/WorkContextAccessor.cs @@ -1,13 +1,11 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; using System.Web; using Autofac; using Orchard.Mvc; namespace Orchard.Environment { - public class DefaultWorkContextAccessor : IWorkContextAccessor { + public class WorkContextAccessor : IWorkContextAccessor { readonly ILifetimeScope _lifetimeScope; readonly IHttpContextAccessor _httpContextAccessor; @@ -18,7 +16,7 @@ namespace Orchard.Environment { [ThreadStatic] static ConcurrentDictionary _threadStaticContexts; - public DefaultWorkContextAccessor( + public WorkContextAccessor( IHttpContextAccessor httpContextAccessor, ILifetimeScope lifetimeScope) { _httpContextAccessor = httpContextAccessor; @@ -39,36 +37,23 @@ namespace Orchard.Environment { } public IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext) { + var workLifetime = _lifetimeScope.BeginLifetimeScope("work"); + workLifetime.Resolve>().Value = httpContext; - var workLifetime = SpawnWorkLifetime(builder => { - builder.Register(ctx => httpContext) - .As(); - - builder.Register(ctx => new WorkContextImplementation(ctx)) - .As() - .InstancePerMatchingLifetimeScope("work"); - }); return new HttpContextScopeImplementation( workLifetime, httpContext, _workContextKey); } + public IWorkContextScope CreateWorkContextScope() { var httpContext = _httpContextAccessor.Current(); if (httpContext != null) return CreateWorkContextScope(httpContext); - var workLifetime = SpawnWorkLifetime(builder => { - builder.Register(ctx => httpContext) - .As(); - - builder.Register(ctx => new WorkContextImplementation(ctx)) - .As() - .InstancePerMatchingLifetimeScope("work"); - }); return new ThreadStaticScopeImplementation( - workLifetime, + _lifetimeScope.BeginLifetimeScope("work"), EnsureThreadStaticContexts(), _workContextKey); } @@ -77,49 +62,6 @@ namespace Orchard.Environment { return _threadStaticContexts ?? (_threadStaticContexts = new ConcurrentDictionary()); } - private ILifetimeScope SpawnWorkLifetime(Action configurationAction) { - return _lifetimeScope.BeginLifetimeScope("work", configurationAction); - } - - class WorkContextImplementation : WorkContext { - readonly IComponentContext _componentContext; - readonly ConcurrentDictionary> _stateResolvers = new ConcurrentDictionary>(); - readonly IEnumerable _workContextStateProviders; - - public WorkContextImplementation(IComponentContext componentContext) { - _componentContext = componentContext; - _workContextStateProviders = componentContext.Resolve>(); - } - - public override T Resolve() { - return _componentContext.Resolve(); - } - - public override bool TryResolve(out T service) { - return _componentContext.TryResolve(out service); - } - - public override T GetState(string name) { - var resolver = _stateResolvers.GetOrAdd(name, FindResolverForState); - return (T)resolver(); - } - - Func FindResolverForState(string name) { - var resolver = _workContextStateProviders.Select(wcsp => wcsp.Get(name)) - .FirstOrDefault(value => !Equals(value, default(T))); - - if (resolver == null) { - return () => default(T); - } - return () => resolver(this); - } - - - public override void SetState(string name, T value) { - _stateResolvers[name] = () => value; - } - } - class HttpContextScopeImplementation : IWorkContextScope { readonly WorkContext _workContext; diff --git a/src/Orchard/Environment/WorkContextImplementation.cs b/src/Orchard/Environment/WorkContextImplementation.cs new file mode 100644 index 000000000..e7f0634b2 --- /dev/null +++ b/src/Orchard/Environment/WorkContextImplementation.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using Autofac; + +namespace Orchard.Environment { + class WorkContextImplementation : WorkContext { + readonly IComponentContext _componentContext; + readonly ConcurrentDictionary> _stateResolvers = new ConcurrentDictionary>(); + readonly IEnumerable _workContextStateProviders; + + public WorkContextImplementation(IComponentContext componentContext) { + _componentContext = componentContext; + _workContextStateProviders = componentContext.Resolve>(); + } + + public override T Resolve() { + return _componentContext.Resolve(); + } + + public override bool TryResolve(out T service) { + return _componentContext.TryResolve(out service); + } + + public override T GetState(string name) { + var resolver = _stateResolvers.GetOrAdd(name, FindResolverForState); + return (T)resolver(); + } + + Func FindResolverForState(string name) { + var resolver = Enumerable.FirstOrDefault(_workContextStateProviders.Select(wcsp => wcsp.Get(name)), value => !Equals(value, default(T))); + + if (resolver == null) { + return () => default(T); + } + return () => resolver(this); + } + + + public override void SetState(string name, T value) { + _stateResolvers[name] = () => value; + } + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/WorkContextModule.cs b/src/Orchard/Environment/WorkContextModule.cs new file mode 100644 index 000000000..49729cda2 --- /dev/null +++ b/src/Orchard/Environment/WorkContextModule.cs @@ -0,0 +1,24 @@ +using System.Web; +using Autofac; + +namespace Orchard.Environment { + public class WorkContextModule : Module { + protected override void Load(ContainerBuilder builder) { + builder.RegisterType() + .As() + .InstancePerMatchingLifetimeScope("shell"); + + builder.Register(ctx => new WorkContextImplementation(ctx)) + .As() + .InstancePerMatchingLifetimeScope("work"); + + builder.RegisterType>() + .As>() + .InstancePerMatchingLifetimeScope("work"); + + builder.Register(ctx => ctx.Resolve>().Value) + .As() + .InstancePerDependency(); + } + } +} diff --git a/src/Orchard/Environment/WorkContextProperty.cs b/src/Orchard/Environment/WorkContextProperty.cs new file mode 100644 index 000000000..8dd6223d0 --- /dev/null +++ b/src/Orchard/Environment/WorkContextProperty.cs @@ -0,0 +1,5 @@ +namespace Orchard.Environment { + class WorkContextProperty { + public T Value { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard/IWorkContextAccessor.cs b/src/Orchard/IWorkContextAccessor.cs index 585b630a4..1f6fec307 100644 --- a/src/Orchard/IWorkContextAccessor.cs +++ b/src/Orchard/IWorkContextAccessor.cs @@ -2,7 +2,7 @@ using System.Web; namespace Orchard { - public interface IWorkContextAccessor : ISingletonDependency { + public interface IWorkContextAccessor { WorkContext GetContext(HttpContextBase httpContext); IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext); diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index a264d31e6..b54a863e2 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -158,6 +158,9 @@ + + + @@ -419,7 +422,7 @@ - +