From c4e1cbeb539f83a4dac819df11009c8203fc2bc7 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Thu, 2 Sep 2010 22:14:07 -0700 Subject: [PATCH] Continued adjustments Removing direct references to IContainer and IContainerProvider from within components Fixing broken tests --HG-- branch : dev --- .../ContentPartDriverCoordinatorTests.cs | 4 +- .../Environment/DefaultOrchardHostTests.cs | 4 -- .../DefaultShellContextFactoryTests.cs | 9 ++++- .../State/DefaultProcessingEngineTests.cs | 7 ++++ .../Mvc/Routes/ShellRouteTests.cs | 5 +++ .../Tasks/SweepGeneratorTests.cs | 37 ++++++++++--------- .../AutofacUtil/ContainerUpdater.cs | 24 ------------ .../Environment/DefaultHostContainer.cs | 3 -- .../Environment/DefaultWorkContextAccessor.cs | 18 +++++---- src/Orchard/Environment/OrchardStarter.cs | 33 +++++------------ .../Localization/LocalizationUtilities.cs | 2 +- src/Orchard/Mvc/Html/ContainerExtensions.cs | 2 +- src/Orchard/Mvc/IHttpContextAccessor.cs | 29 ++++++++++++++- src/Orchard/Mvc/OrchardControllerFactory.cs | 2 +- .../Mvc/ViewEngines/Razor/WebViewPage.cs | 3 +- src/Orchard/Orchard.Framework.csproj | 1 - src/Orchard/Tasks/SweepGenerator.cs | 10 ++--- src/Orchard/WorkContext.cs | 6 ++- 18 files changed, 104 insertions(+), 95 deletions(-) delete mode 100644 src/Orchard/Environment/AutofacUtil/ContainerUpdater.cs diff --git a/src/Orchard.Tests/ContentManagement/Handlers/Coordinators/ContentPartDriverCoordinatorTests.cs b/src/Orchard.Tests/ContentManagement/Handlers/Coordinators/ContentPartDriverCoordinatorTests.cs index 165c4734a..76763b65c 100644 --- a/src/Orchard.Tests/ContentManagement/Handlers/Coordinators/ContentPartDriverCoordinatorTests.cs +++ b/src/Orchard.Tests/ContentManagement/Handlers/Coordinators/ContentPartDriverCoordinatorTests.cs @@ -36,7 +36,7 @@ namespace Orchard.Tests.ContentManagement.Handlers.Coordinators { public void AllDriversShouldBeCalled() { var driver1 = new Mock(); var driver2 = new Mock(); - var builder = new ContainerUpdater(); + var builder = new ContainerBuilder(); builder.RegisterInstance(driver1.Object); builder.RegisterInstance(driver2.Object); builder.Update(_container); @@ -52,7 +52,7 @@ namespace Orchard.Tests.ContentManagement.Handlers.Coordinators { [Test] public void TestDriverCanAddDisplay() { var driver = new StubPartDriver(); - var builder = new ContainerUpdater(); + var builder = new ContainerBuilder(); builder.RegisterInstance(driver).As(); builder.Update(_container); diff --git a/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs b/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs index ec2f88bf7..77b9b5e3e 100644 --- a/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs +++ b/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs @@ -50,7 +50,6 @@ namespace Orchard.Tests.Environment { _container = OrchardStarter.CreateHostContainer( builder => { builder.RegisterInstance(new StubShellSettingsLoader()).As(); - builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); @@ -81,9 +80,6 @@ namespace Orchard.Tests.Environment { _container.Mock() .Setup(e => e.Activated()); - var updater = new ContainerUpdater(); - updater.RegisterInstance(_container).SingleInstance(); - updater.Update(_lifetime); } public class StubExtensionManager : IExtensionManager { diff --git a/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs b/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs index dfe2395df..56a96df61 100644 --- a/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs +++ b/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs @@ -1,4 +1,5 @@ -using Autofac; +using System.Web; +using Autofac; using Autofac.Core.Registration; using Moq; using NUnit.Framework; @@ -8,6 +9,7 @@ using Orchard.Environment.ShellBuilders; using Orchard.Environment.Descriptor; using Orchard.Environment.Descriptor.Models; using Orchard.Environment.ShellBuilders.Models; +using Orchard.Mvc; using Orchard.Tests.Utility; namespace Orchard.Tests.Environment.ShellBuilders { @@ -19,6 +21,7 @@ namespace Orchard.Tests.Environment.ShellBuilders { public void Init() { var builder = new ContainerBuilder(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterAutoMocking(Moq.MockBehavior.Strict); _container = builder.Build(); } @@ -46,6 +49,10 @@ namespace Orchard.Tests.Environment.ShellBuilders { .Setup(x => x.GetShellDescriptor()) .Returns(descriptor); + _container.Mock() + .Setup(x => x.Current()) + .Returns(default(HttpContextBase)); + var factory = _container.Resolve(); var context = factory.CreateShellContext(settings); diff --git a/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs b/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs index 06af55624..e35a2f401 100644 --- a/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs +++ b/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs @@ -1,13 +1,16 @@ using System.Collections.Generic; using System.Linq; +using System.Web; using Autofac; using Moq; using NUnit.Framework; +using Orchard.Environment; using Orchard.Environment.Configuration; using Orchard.Environment.ShellBuilders; using Orchard.Environment.State; using Orchard.Environment.Descriptor.Models; using Orchard.Events; +using Orchard.Mvc; using Orchard.Tests.Utility; namespace Orchard.Tests.Environment.State { @@ -20,6 +23,7 @@ namespace Orchard.Tests.Environment.State { public void Init() { var builder = new ContainerBuilder(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterAutoMocking(); _container = builder.Build(); @@ -32,6 +36,9 @@ namespace Orchard.Tests.Environment.State { _container.Mock() .Setup(x => x.CreateDescribedContext(_shellContext.Settings, _shellContext.Descriptor)) .Returns(_shellContext); + _container.Mock() + .Setup(x=>x.Current()) + .Returns(default(HttpContextBase)); } diff --git a/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs b/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs index dea1069c2..b1ae663f3 100644 --- a/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs +++ b/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs @@ -11,6 +11,7 @@ using Moq; using NUnit.Framework; using Orchard.Environment; using Orchard.Environment.Configuration; +using Orchard.Mvc; using Orchard.Mvc.Routes; using Orchard.Tests.Stubs; using Orchard.Tests.Utility; @@ -35,16 +36,20 @@ namespace Orchard.Tests.Mvc.Routes { rootBuilder.Register(ctx => _routes); rootBuilder.RegisterType().InstancePerDependency(); rootBuilder.RegisterType().As().SingleInstance(); + rootBuilder.RegisterType().As().InstancePerMatchingLifetimeScope("shell"); + rootBuilder.RegisterType().As(); _rootContainer = rootBuilder.Build(); _containerA = _rootContainer.BeginLifetimeScope( + "shell", builder => { builder.Register(ctx => _settingsA); builder.RegisterType().As().InstancePerLifetimeScope(); }); _containerB = _rootContainer.BeginLifetimeScope( + "shell", builder => { builder.Register(ctx => _settingsB); builder.RegisterType().As().InstancePerLifetimeScope(); diff --git a/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs b/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs index 2c7301c9d..9e0469631 100644 --- a/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs +++ b/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs @@ -2,42 +2,43 @@ using Autofac; using Moq; using NUnit.Framework; +using Orchard.Environment; +using Orchard.Mvc; using Orchard.Tasks; +using Orchard.Tests.Utility; namespace Orchard.Tests.Tasks { [TestFixture] - public class SweepGeneratorTests { + public class SweepGeneratorTests : ContainerTestBase { + protected override void Register(ContainerBuilder builder) { + builder.RegisterAutoMocking(MockBehavior.Loose); + builder.RegisterType().As(); + builder.RegisterType(); + } [Test] public void DoWorkShouldSendHeartbeatToTaskManager() { - var taskManager = new Mock(); - - var builder = new ContainerBuilder(); - builder.RegisterInstance(taskManager.Object); - var container = builder.Build(); - - var heartbeatSource = new SweepGenerator(container); + var heartbeatSource = _container.Resolve(); heartbeatSource.DoWork(); - taskManager.Verify(x => x.Sweep(), Times.Once()); + _container.Resolve>() + .Verify(x => x.Sweep(), Times.Once()); } [Test] public void ActivatedEventShouldStartTimer() { - var taskManager = new Mock(); - var builder = new ContainerBuilder(); - builder.RegisterInstance(taskManager.Object); - var container = builder.Build(); + var heartbeatSource = _container.Resolve(); + heartbeatSource.Interval = TimeSpan.FromMilliseconds(25); - var heartbeatSource = new SweepGenerator(container) { - Interval = TimeSpan.FromMilliseconds(25) - }; + _container.Resolve>() + .Verify(x => x.Sweep(), Times.Never()); - taskManager.Verify(x => x.Sweep(), Times.Never()); heartbeatSource.Activated(); System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(80)); heartbeatSource.Terminating(); - taskManager.Verify(x => x.Sweep(), Times.AtLeastOnce()); + + _container.Resolve>() + .Verify(x => x.Sweep(), Times.AtLeastOnce()); } } } diff --git a/src/Orchard/Environment/AutofacUtil/ContainerUpdater.cs b/src/Orchard/Environment/AutofacUtil/ContainerUpdater.cs deleted file mode 100644 index 4ebf29bae..000000000 --- a/src/Orchard/Environment/AutofacUtil/ContainerUpdater.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using Autofac; -using Autofac.Core; - -namespace Orchard.Environment.AutofacUtil { - public class ContainerUpdater : ContainerBuilder { - readonly ICollection> _configurationActions = new List>(); - - public override void RegisterCallback(Action configurationAction) { - _configurationActions.Add(configurationAction); - } - - public void Update(IContainer container) { - foreach (var action in _configurationActions) - action(container.ComponentRegistry); - } - - public void Update(ILifetimeScope container) { - foreach (var action in _configurationActions) - action(container.ComponentRegistry); - } - } -} \ No newline at end of file diff --git a/src/Orchard/Environment/DefaultHostContainer.cs b/src/Orchard/Environment/DefaultHostContainer.cs index d546508ee..ac26f22bb 100644 --- a/src/Orchard/Environment/DefaultHostContainer.cs +++ b/src/Orchard/Environment/DefaultHostContainer.cs @@ -2,13 +2,10 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Web; using System.Web.Mvc; using Autofac; -using Autofac.Integration.Web; namespace Orchard.Environment { - //IContainerProvider public class DefaultOrchardHostContainer : IOrchardHostContainer, IMvcServiceLocator { private readonly IContainer _container; diff --git a/src/Orchard/Environment/DefaultWorkContextAccessor.cs b/src/Orchard/Environment/DefaultWorkContextAccessor.cs index d3184c8ab..2f2e780c0 100644 --- a/src/Orchard/Environment/DefaultWorkContextAccessor.cs +++ b/src/Orchard/Environment/DefaultWorkContextAccessor.cs @@ -15,7 +15,7 @@ namespace Orchard.Environment { readonly object _workContextKey = new object(); [ThreadStatic] - static readonly ConcurrentDictionary _threadStaticContexts = new ConcurrentDictionary(); + static ConcurrentDictionary _threadStaticContexts; public DefaultWorkContextAccessor( IHttpContextAccessor httpContextAccessor, @@ -36,7 +36,7 @@ namespace Orchard.Environment { return GetContext(httpContext); WorkContext workContext; - return _threadStaticContexts.TryGetValue(_workContextKey, out workContext) ? workContext : null; + return EnsureThreadStaticContexts().TryGetValue(_workContextKey, out workContext) ? workContext : null; } public IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext) { @@ -71,10 +71,14 @@ namespace Orchard.Environment { }); return new ThreadStaticScopeImplementation( workLifetime, - _threadStaticContexts, + EnsureThreadStaticContexts(), _workContextKey); } + static ConcurrentDictionary EnsureThreadStaticContexts() { + return _threadStaticContexts ?? (_threadStaticContexts = new ConcurrentDictionary()); + } + private ILifetimeScope SpawnWorkLifetime(Action configurationAction) { return _lifetimeScope.BeginLifetimeScope("work", configurationAction); } @@ -87,8 +91,8 @@ namespace Orchard.Environment { _componentContext = componentContext; } - public override T Service() { - throw new NotImplementedException(); + public override T Resolve() { + return _componentContext.Resolve(); } public override T State() { @@ -118,7 +122,7 @@ namespace Orchard.Environment { } public TService Resolve() { - return WorkContext.Service(); + return WorkContext.Resolve(); } } @@ -145,7 +149,7 @@ namespace Orchard.Environment { } public TService Resolve() { - return WorkContext.Service(); + return WorkContext.Resolve(); } } } diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs index 0a40fb8e3..5195c5072 100644 --- a/src/Orchard/Environment/OrchardStarter.cs +++ b/src/Orchard/Environment/OrchardStarter.cs @@ -22,6 +22,7 @@ using Orchard.FileSystems.Dependencies; using Orchard.FileSystems.VirtualPath; using Orchard.FileSystems.WebSite; using Orchard.Logging; +using Orchard.Mvc; using Orchard.Services; namespace Orchard.Environment { @@ -43,6 +44,7 @@ namespace Orchard.Environment { builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); RegisterVolatileProvider(builder); RegisterVolatileProvider(builder); @@ -60,23 +62,18 @@ namespace Orchard.Environment { { builder.RegisterType().As().SingleInstance(); - builder.RegisterType() - .As() - .SingleInstance(); + builder.RegisterType().As().SingleInstance(); { builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); { - builder.RegisterType().As() - .WithParameter(new NamedParameter("paths", new[] { "~/Core", "~/Modules" })) - .SingleInstance(); - builder.RegisterType().As() - .WithParameter(new NamedParameter("paths", new[] { "~/Areas" })) - .SingleInstance(); - builder.RegisterType().As() - .WithParameter(new NamedParameter("paths", new[] { "~/Core", "~/Themes" })) - .SingleInstance(); + builder.RegisterType().As().SingleInstance() + .WithParameter(new NamedParameter("paths", new[] { "~/Core", "~/Modules" })); + builder.RegisterType().As().SingleInstance() + .WithParameter(new NamedParameter("paths", new[] { "~/Areas" })); + builder.RegisterType().As().SingleInstance() + .WithParameter(new NamedParameter("paths", new[] { "~/Core", "~/Themes" })); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); @@ -96,13 +93,6 @@ namespace Orchard.Environment { builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().InstancePerMatchingLifetimeScope("shell"); - // The container provider gives you access to the lowest container at the time, - // and dynamically creates a per-request container. The EndRequestLifetime method - // still needs to be called on end request, but that's the host component's job to worry about - //builder.RegisterType().As().InstancePerLifetimeScope(); - - - registrations(builder); @@ -114,10 +104,6 @@ namespace Orchard.Environment { if (File.Exists(optionalHostConfig)) builder.RegisterModule(new ConfigurationSettingsReader(ConfigurationSettingsReader.DefaultSectionName, optionalHostConfig)); - builder - .Register(ctx => new LifetimeScopeContainer(ctx.Resolve())) - .As() - .InstancePerMatchingLifetimeScope("shell"); var container = builder.Build(); @@ -137,6 +123,7 @@ namespace Orchard.Environment { return container; } + private static void RegisterVolatileProvider(ContainerBuilder builder) where TService : IVolatileProvider { builder.RegisterType() .As() diff --git a/src/Orchard/Localization/LocalizationUtilities.cs b/src/Orchard/Localization/LocalizationUtilities.cs index 7de753aa9..c47cd6fa8 100644 --- a/src/Orchard/Localization/LocalizationUtilities.cs +++ b/src/Orchard/Localization/LocalizationUtilities.cs @@ -6,7 +6,7 @@ namespace Orchard.Localization { public class LocalizationUtilities { public static Localizer Resolve(ControllerContext controllerContext, string scope) { var context = controllerContext.GetWorkContext(); - return context == null ? NullLocalizer.Instance : Resolve(context.Service(), scope); + return context == null ? NullLocalizer.Instance : Resolve(context.Resolve(), scope); } public static Localizer Resolve(IComponentContext context, string scope) { diff --git a/src/Orchard/Mvc/Html/ContainerExtensions.cs b/src/Orchard/Mvc/Html/ContainerExtensions.cs index 167433e8c..88ab0a38f 100644 --- a/src/Orchard/Mvc/Html/ContainerExtensions.cs +++ b/src/Orchard/Mvc/Html/ContainerExtensions.cs @@ -19,7 +19,7 @@ namespace Orchard.Mvc.Html { if (workContext == null) throw new ApplicationException("Unable to resolve"); - return workContext.Service(); + return workContext.Resolve(); } } } \ No newline at end of file diff --git a/src/Orchard/Mvc/IHttpContextAccessor.cs b/src/Orchard/Mvc/IHttpContextAccessor.cs index d456bce2e..ee79e4527 100644 --- a/src/Orchard/Mvc/IHttpContextAccessor.cs +++ b/src/Orchard/Mvc/IHttpContextAccessor.cs @@ -1,7 +1,34 @@ -using System.Web; +using System; +using System.Web; namespace Orchard.Mvc { public interface IHttpContextAccessor { HttpContextBase Current(); } + + public class HttpContextAccessor : IHttpContextAccessor { + public HttpContextBase Current() { + var httpContext = GetStaticProperty(); + if (httpContext == null) + return null; + return new HttpContextWrapper(httpContext); + } + + private HttpContext GetStaticProperty() { + var httpContext = HttpContext.Current; + if (httpContext == null) { + return null; + } + + try { + if (httpContext.Request == null) { + return null; + } + } + catch (Exception) { + return null; + } + return httpContext; + } + } } diff --git a/src/Orchard/Mvc/OrchardControllerFactory.cs b/src/Orchard/Mvc/OrchardControllerFactory.cs index 2f9a7c87f..61eca3d7a 100644 --- a/src/Orchard/Mvc/OrchardControllerFactory.cs +++ b/src/Orchard/Mvc/OrchardControllerFactory.cs @@ -26,7 +26,7 @@ namespace Orchard.Mvc { var workContext = workContextAccessor != null ? workContextAccessor.GetContext(requestContext.HttpContext) : null; if (workContext != null && - workContext.Service().TryResolve(service, out controller)) { + workContext.Resolve().TryResolve(service, out controller)) { return (IController)controller; } diff --git a/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs b/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs index 538a99968..9b9c975e4 100644 --- a/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs +++ b/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs @@ -19,7 +19,6 @@ namespace Orchard.Mvc.ViewEngines.Razor { public abstract class WebViewPage : System.Web.Mvc.WebViewPage { private object _display; private Localizer _localizer = NullLocalizer.Instance; - private IEnumerable _contexturalizers = Enumerable.Empty(); public Localizer T { get { return _localizer; } } @@ -32,7 +31,7 @@ namespace Orchard.Mvc.ViewEngines.Razor { base.InitHelpers(); var workContext = ViewContext.GetWorkContext(); - workContext.Service().InjectUnsetProperties(this); + workContext.Resolve().InjectUnsetProperties(this); _localizer = LocalizationUtilities.Resolve(ViewContext, VirtualPath); _display = DisplayHelperFactory.CreateHelper(ViewContext, this); diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 7736ddf57..8ef923f50 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -603,7 +603,6 @@ - diff --git a/src/Orchard/Tasks/SweepGenerator.cs b/src/Orchard/Tasks/SweepGenerator.cs index 47c39a7e0..627838b9a 100644 --- a/src/Orchard/Tasks/SweepGenerator.cs +++ b/src/Orchard/Tasks/SweepGenerator.cs @@ -6,11 +6,11 @@ using Orchard.Logging; namespace Orchard.Tasks { public class SweepGenerator : IOrchardShellEvents { - private readonly IContainer _container; + private readonly IWorkContextAccessor _workContextAccessor; private readonly Timer _timer; - public SweepGenerator(IContainer container) { - _container = container; + public SweepGenerator(IWorkContextAccessor workContextAccessor) { + _workContextAccessor = workContextAccessor; _timer = new Timer(); _timer.Elapsed += Elapsed; Logger = NullLogger.Instance; @@ -56,9 +56,9 @@ namespace Orchard.Tasks { public void DoWork() { // makes an inner container, similar to the per-request container - using (var standaloneEnvironment = _container.CreateWorkContextScope()) { + using (var scope = _workContextAccessor.CreateWorkContextScope()) { // resolve the manager and invoke it - var manager = standaloneEnvironment.Resolve(); + var manager = scope.Resolve(); manager.Sweep(); } } diff --git a/src/Orchard/WorkContext.cs b/src/Orchard/WorkContext.cs index 466aaa637..87c5a6e41 100644 --- a/src/Orchard/WorkContext.cs +++ b/src/Orchard/WorkContext.cs @@ -1,4 +1,5 @@ using System; +using System.Web; using Autofac; using Orchard.Security; using Orchard.Settings; @@ -6,6 +7,9 @@ using Orchard.UI; namespace Orchard { public abstract class WorkContext { + public HttpContextBase HttpContext { + get { return State(); } + } public IPage CurrentPage { get { return State(); } } @@ -16,7 +20,7 @@ namespace Orchard { get { return State(); } } - public abstract T Service(); + public abstract T Resolve(); public abstract T State(); } } \ No newline at end of file