diff --git a/src/Orchard.Core.Tests/Body/BodyPartTests.cs b/src/Orchard.Core.Tests/Body/BodyPartTests.cs index a899d8246..17fa1bbf4 100644 --- a/src/Orchard.Core.Tests/Body/BodyPartTests.cs +++ b/src/Orchard.Core.Tests/Body/BodyPartTests.cs @@ -38,6 +38,7 @@ namespace Orchard.Core.Tests.Body { builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Core.Tests/Common/Providers/CommonPartProviderTests.cs b/src/Orchard.Core.Tests/Common/Providers/CommonPartProviderTests.cs index a963c2f66..408595d28 100644 --- a/src/Orchard.Core.Tests/Common/Providers/CommonPartProviderTests.cs +++ b/src/Orchard.Core.Tests/Common/Providers/CommonPartProviderTests.cs @@ -66,6 +66,7 @@ namespace Orchard.Core.Tests.Common.Providers { builder.RegisterInstance(new RequestContext(new StubHttpContext(), new RouteData())); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs b/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs index 084ec8512..693c99c0f 100644 --- a/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs +++ b/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs @@ -54,6 +54,7 @@ namespace Orchard.Core.Tests.Routable.Services { builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Core.Tests/Scheduling/ScheduledTaskExecutorTests.cs b/src/Orchard.Core.Tests/Scheduling/ScheduledTaskExecutorTests.cs index 1dae6ce97..138fd6384 100644 --- a/src/Orchard.Core.Tests/Scheduling/ScheduledTaskExecutorTests.cs +++ b/src/Orchard.Core.Tests/Scheduling/ScheduledTaskExecutorTests.cs @@ -36,6 +36,7 @@ namespace Orchard.Core.Tests.Scheduling { builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterInstance(new Mock().Object); builder.RegisterInstance(new Mock().Object); diff --git a/src/Orchard.Core.Tests/Scheduling/ScheduledTaskManagerTests.cs b/src/Orchard.Core.Tests/Scheduling/ScheduledTaskManagerTests.cs index 577fab442..5986d8248 100644 --- a/src/Orchard.Core.Tests/Scheduling/ScheduledTaskManagerTests.cs +++ b/src/Orchard.Core.Tests/Scheduling/ScheduledTaskManagerTests.cs @@ -40,6 +40,7 @@ namespace Orchard.Core.Tests.Scheduling { builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterInstance(new Mock().Object); builder.RegisterInstance(new Mock().Object); diff --git a/src/Orchard.Tests.Modules/Users/Controllers/AccountControllerTests.cs b/src/Orchard.Tests.Modules/Users/Controllers/AccountControllerTests.cs index 6d9dddc3d..d1b3cf64c 100644 --- a/src/Orchard.Tests.Modules/Users/Controllers/AccountControllerTests.cs +++ b/src/Orchard.Tests.Modules/Users/Controllers/AccountControllerTests.cs @@ -70,6 +70,7 @@ namespace Orchard.Tests.Modules.Users.Controllers { builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Tests/ContentManagement/ContentQueryTests.cs b/src/Orchard.Tests/ContentManagement/ContentQueryTests.cs index cc6d6c553..e34f7f8f4 100644 --- a/src/Orchard.Tests/ContentManagement/ContentQueryTests.cs +++ b/src/Orchard.Tests/ContentManagement/ContentQueryTests.cs @@ -56,6 +56,7 @@ namespace Orchard.Tests.ContentManagement { builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); diff --git a/src/Orchard.Tests/ContentManagement/DefaultContentManagerTests.cs b/src/Orchard.Tests/ContentManagement/DefaultContentManagerTests.cs index 2f6f706fc..e583f5004 100644 --- a/src/Orchard.Tests/ContentManagement/DefaultContentManagerTests.cs +++ b/src/Orchard.Tests/ContentManagement/DefaultContentManagerTests.cs @@ -68,6 +68,7 @@ namespace Orchard.Tests.ContentManagement { builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Tests/DisplayManagement/DefaultDisplayManagerTests.cs b/src/Orchard.Tests/DisplayManagement/DefaultDisplayManagerTests.cs index c3d2099ba..0dbede940 100644 --- a/src/Orchard.Tests/DisplayManagement/DefaultDisplayManagerTests.cs +++ b/src/Orchard.Tests/DisplayManagement/DefaultDisplayManagerTests.cs @@ -27,6 +27,7 @@ namespace Orchard.Tests.DisplayManagement { builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As() .As() diff --git a/src/Orchard.Tests/DisplayManagement/ShapeFactoryTests.cs b/src/Orchard.Tests/DisplayManagement/ShapeFactoryTests.cs index ffd4ca289..7ee8a5964 100644 --- a/src/Orchard.Tests/DisplayManagement/ShapeFactoryTests.cs +++ b/src/Orchard.Tests/DisplayManagement/ShapeFactoryTests.cs @@ -10,7 +10,7 @@ using Orchard.Tests.Stubs; namespace Orchard.Tests.DisplayManagement { [TestFixture] - public class DefaultShapeBuilderTests { + public class ShapeFactoryTests { private IContainer _container; [SetUp] @@ -18,6 +18,7 @@ namespace Orchard.Tests.DisplayManagement { var builder = new ContainerBuilder(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Tests/DisplayManagement/ShapeHelperTests.cs b/src/Orchard.Tests/DisplayManagement/ShapeHelperTests.cs index 36ab18689..0d7ec85d0 100644 --- a/src/Orchard.Tests/DisplayManagement/ShapeHelperTests.cs +++ b/src/Orchard.Tests/DisplayManagement/ShapeHelperTests.cs @@ -17,6 +17,7 @@ namespace Orchard.Tests.DisplayManagement { var builder = new ContainerBuilder(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Tests/DisplayManagement/SubsystemTests.cs b/src/Orchard.Tests/DisplayManagement/SubsystemTests.cs index f57ba0c73..473a825b6 100644 --- a/src/Orchard.Tests/DisplayManagement/SubsystemTests.cs +++ b/src/Orchard.Tests/DisplayManagement/SubsystemTests.cs @@ -43,6 +43,7 @@ namespace Orchard.Tests.DisplayManagement { var builder = new ContainerBuilder(); builder.RegisterModule(new ShapeAttributeBindingModule()); 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 50ddb32f6..f4653e94b 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs @@ -84,6 +84,7 @@ namespace Orchard.Setup { builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard/ContentManagement/DefaultContentDisplay.cs b/src/Orchard/ContentManagement/DefaultContentDisplay.cs index dccd0c448..ea5448980 100644 --- a/src/Orchard/ContentManagement/DefaultContentDisplay.cs +++ b/src/Orchard/ContentManagement/DefaultContentDisplay.cs @@ -8,32 +8,32 @@ using Orchard.DisplayManagement; using Orchard.DisplayManagement.Descriptors; using Orchard.FileSystems.VirtualPath; using Orchard.Logging; -using Orchard.Themes; using Orchard.UI.Zones; namespace Orchard.ContentManagement { public class DefaultContentDisplay : IContentDisplay { private readonly Lazy> _handlers; private readonly IShapeFactory _shapeFactory; - private readonly IShapeTableManager _shapeTableManager; - private readonly Lazy _themeService; + private readonly Lazy _shapeTableLocator; + private readonly RequestContext _requestContext; private readonly IVirtualPathProvider _virtualPathProvider; + private readonly IWorkContextAccessor _workContextAccessor; public DefaultContentDisplay( Lazy> handlers, IShapeFactory shapeFactory, - IShapeTableManager shapeTableManager, - Lazy themeService, + Lazy shapeTableLocator, RequestContext requestContext, - IVirtualPathProvider virtualPathProvider) { + IVirtualPathProvider virtualPathProvider, + IWorkContextAccessor workContextAccessor) { _handlers = handlers; _shapeFactory = shapeFactory; - _shapeTableManager = shapeTableManager; - _themeService = themeService; + _shapeTableLocator = shapeTableLocator; _requestContext = requestContext; _virtualPathProvider = virtualPathProvider; + _workContextAccessor = workContextAccessor; Logger = NullLogger.Instance; } @@ -106,8 +106,11 @@ namespace Orchard.ContentManagement { private void BindPlacement(BuildShapeContext context, string displayType, string stereotype) { context.FindPlacement = (partShapeType, differentiator, defaultLocation) => { - var theme = _themeService.Value.GetRequestTheme(_requestContext); - var shapeTable = _shapeTableManager.GetShapeTable(theme.Id); + var workContext = _workContextAccessor.GetContext(_requestContext.HttpContext); + + var theme = workContext.CurrentTheme; + var shapeTable = _shapeTableLocator.Value.Lookup(theme.Id); + var request = _requestContext.HttpContext.Request; ShapeDescriptor descriptor; diff --git a/src/Orchard/ContentManagement/DefaultContentManager.cs b/src/Orchard/ContentManagement/DefaultContentManager.cs index b1317c871..f7103d119 100644 --- a/src/Orchard/ContentManagement/DefaultContentManager.cs +++ b/src/Orchard/ContentManagement/DefaultContentManager.cs @@ -15,7 +15,6 @@ using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.Records; using Orchard.Data; -using Orchard.Environment; using Orchard.Indexing; using Orchard.Logging; using Orchard.UI; @@ -29,7 +28,7 @@ namespace Orchard.ContentManagement { private readonly IContentDefinitionManager _contentDefinitionManager; private readonly Func _contentManagerSession; private readonly Lazy _contentDisplay; - private readonly Work _sessionLocator; + private readonly Lazy _sessionLocator; private const string Published = "Published"; private const string Draft = "Draft"; @@ -41,7 +40,7 @@ namespace Orchard.ContentManagement { IContentDefinitionManager contentDefinitionManager, Func contentManagerSession, Lazy contentDisplay, - Work sessionLocator) { + Lazy sessionLocator) { _context = context; _contentTypeRepository = contentTypeRepository; _contentItemRepository = contentItemRepository; diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeTableLocator.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeTableLocator.cs new file mode 100644 index 000000000..6fc0de1c8 --- /dev/null +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeTableLocator.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Concurrent; + +namespace Orchard.DisplayManagement.Descriptors +{ + + /// + /// Will return the same shape table per name within the same unit of work. + /// Reduces compute costs compared to IShapeTableManager.GetShapeTable. + /// + public interface IShapeTableLocator : IUnitOfWorkDependency + { + ShapeTable Lookup(string themeName); + } + + public class ShapeTableLocator : IShapeTableLocator + { + private readonly IShapeTableManager _shapeTableManager; + readonly ConcurrentDictionary _shapeTables = new ConcurrentDictionary(); + + public ShapeTableLocator(IShapeTableManager shapeTableManager) + { + _shapeTableManager = shapeTableManager; + } + + public ShapeTable Lookup(string themeName) + { + return _shapeTables.GetOrAdd(themeName ?? "", _ => _shapeTableManager.GetShapeTable(themeName)); + } + } +} \ No newline at end of file diff --git a/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs b/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs index ef30ce852..5d00298dc 100644 --- a/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs +++ b/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs @@ -13,7 +13,7 @@ using Orchard.Logging; namespace Orchard.DisplayManagement.Implementation { public class DefaultDisplayManager : IDisplayManager { - private readonly IShapeTableManager _shapeTableManager; + private readonly Lazy _shapeTableLocator; private readonly IWorkContextAccessor _workContextAccessor; private readonly IEnumerable _shapeDisplayEvents; @@ -26,10 +26,10 @@ namespace Orchard.DisplayManagement.Implementation { null/*typeof(DefaultDisplayManager)*/))); public DefaultDisplayManager( - IShapeTableManager shapeTableManager, IWorkContextAccessor workContextAccessor, - IEnumerable shapeDisplayEvents) { - _shapeTableManager = shapeTableManager; + IEnumerable shapeDisplayEvents, + Lazy shapeTableLocator) { + _shapeTableLocator = shapeTableLocator; _workContextAccessor = workContextAccessor; _shapeDisplayEvents = shapeDisplayEvents; T = NullLocalizer.Instance; @@ -53,7 +53,7 @@ namespace Orchard.DisplayManagement.Implementation { return CoerceHtmlString(context.Value); var workContext = _workContextAccessor.GetContext(context.ViewContext); - var shapeTable = _shapeTableManager.GetShapeTable(workContext.CurrentTheme.Id); + var shapeTable = _shapeTableLocator.Value.Lookup(workContext.CurrentTheme.Id); var displayingContext = new ShapeDisplayingContext { Shape = shape, diff --git a/src/Orchard/DisplayManagement/Implementation/DefaultShapeFactory.cs b/src/Orchard/DisplayManagement/Implementation/DefaultShapeFactory.cs index a295bb240..2ba84fa50 100644 --- a/src/Orchard/DisplayManagement/Implementation/DefaultShapeFactory.cs +++ b/src/Orchard/DisplayManagement/Implementation/DefaultShapeFactory.cs @@ -9,13 +9,14 @@ namespace Orchard.DisplayManagement.Implementation { public class DefaultShapeFactory : Clay, IShapeFactory { private readonly IEnumerable> _events; - private readonly IShapeTableManager _shapeTableManager; + private readonly Lazy _shapeTableLocator; public DefaultShapeFactory( IEnumerable> events, - IShapeTableManager shapeTableManager) : base(new ShapeFactoryBehavior()) { + Lazy shapeTableLocator) : base(new ShapeFactoryBehavior()) + { _events = events; - _shapeTableManager = shapeTableManager; + _shapeTableLocator = shapeTableLocator; } class ShapeFactoryBehavior : ClayBehavior { @@ -29,7 +30,7 @@ namespace Orchard.DisplayManagement.Implementation { } public IShape Create(string shapeType, INamedEnumerable parameters, IEnumerable behaviors) { - var defaultShapeTable = _shapeTableManager.GetShapeTable(null); + var defaultShapeTable = _shapeTableLocator.Value.Lookup(null); ShapeDescriptor shapeDescriptor; defaultShapeTable.Descriptors.TryGetValue(shapeType, out shapeDescriptor); diff --git a/src/Orchard/Themes/CurrentThemeWorkContext.cs b/src/Orchard/Themes/CurrentThemeWorkContext.cs new file mode 100644 index 000000000..0f97ae681 --- /dev/null +++ b/src/Orchard/Themes/CurrentThemeWorkContext.cs @@ -0,0 +1,27 @@ +using System; +using Orchard.Mvc; + +namespace Orchard.Themes +{ + public class CurrentThemeWorkContext : IWorkContextStateProvider + { + private readonly IThemeManager _themeManager; + private readonly IHttpContextAccessor _httpContextAccessor; + + public CurrentThemeWorkContext(IThemeManager themeManager, IHttpContextAccessor httpContextAccessor) + { + _themeManager = themeManager; + _httpContextAccessor = httpContextAccessor; + } + + public Func Get(string name) + { + if (name == "CurrentTheme") + { + var currentTheme = _themeManager.GetRequestTheme(_httpContextAccessor.Current().Request.RequestContext); + return ctx => (T)(object)currentTheme; + } + return null; + } + } +}