diff --git a/src/Umbraco.Core/IMainDom.cs b/src/Umbraco.Core/IMainDom.cs new file mode 100644 index 0000000000..3a8cd13ff1 --- /dev/null +++ b/src/Umbraco.Core/IMainDom.cs @@ -0,0 +1,38 @@ +using System; + +namespace Umbraco.Core +{ + /// + /// Represents the main AppDomain running for a given application. + /// + /// + /// There can be only one "main" AppDomain running for a given application at a time. + /// It is possible to register against the MainDom and be notified when it is released. + /// + public interface IMainDom + { + /// + /// Gets a value indicating whether the current domain is the main domain. + /// + bool IsMainDom { get; } + + /// + /// Registers a resource that requires the current AppDomain to be the main domain to function. + /// + /// An action to execute before the AppDomain releases the main domain status. + /// An optional weight (lower goes first). + /// A value indicating whether it was possible to register. + bool Register(Action release, int weight = 100); + + /// + /// Registers a resource that requires the current AppDomain to be the main domain to function. + /// + /// An action to execute when registering. + /// An action to execute before the AppDomain releases the main domain status. + /// An optional weight (lower goes first). + /// A value indicating whether it was possible to register. + /// If registering is successful, then the action + /// is guaranteed to execute before the AppDomain releases the main domain status. + bool Register(Action install, Action release, int weight = 100); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/MainDom.cs b/src/Umbraco.Core/MainDom.cs index eb036fd441..0bbefe3546 100644 --- a/src/Umbraco.Core/MainDom.cs +++ b/src/Umbraco.Core/MainDom.cs @@ -8,13 +8,11 @@ using Umbraco.Core.Logging; namespace Umbraco.Core { /// - /// Represents the main AppDomain running for a given application. + /// Provides the full implementation of . /// /// - /// There can be only one "main" AppDomain running for a given application at a time. /// When an AppDomain starts, it tries to acquire the main domain status. /// When an AppDomain stops (eg the application is restarting) it should release the main domain status. - /// It is possible to register against the MainDom and be notified when it is released. /// internal class MainDom : IRegisteredObject { @@ -84,9 +82,7 @@ namespace Umbraco.Core /// An optional weight (lower goes first). /// A value indicating whether it was possible to register. public bool Register(Action release, int weight = 100) - { - return Register(null, release, weight); - } + => Register(null, release, weight); /// /// Registers a resource that requires the current AppDomain to be the main domain to function. @@ -195,7 +191,9 @@ namespace Umbraco.Core } } - // gets a value indicating whether we are the main domain + /// + /// Gets a value indicating whether the current domain is the main domain. + /// public bool IsMainDom => _isMainDom; // IRegisteredObject diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index fff865e097..106d2b9f12 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -66,7 +66,7 @@ namespace Umbraco.Core.Services.Implement IEntityService entityService, IUserService userService, IScopeProvider scopeProvider, - IEnumerable urlSegmentProviders, + UrlSegmentProviderCollection urlSegmentProviders, IAuditRepository auditRepository, IContentTypeRepository contentTypeRepository, PropertyEditorCollection propertyEditors) { diff --git a/src/Umbraco.Core/SimpleMainDom.cs b/src/Umbraco.Core/SimpleMainDom.cs new file mode 100644 index 0000000000..87cc7bcff1 --- /dev/null +++ b/src/Umbraco.Core/SimpleMainDom.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Umbraco.Core +{ + /// + /// Provides a simple implementation of . + /// + public class SimpleMainDom : IMainDom + { + private readonly object _locko = new object(); + private readonly List> _callbacks = new List>(); + private bool _isStopping; + + /// + public bool IsMainDom { get; private set; } = true; + + /// + public bool Register(Action release, int weight = 100) + => Register(null, release, weight); + + /// + public bool Register(Action install, Action release, int weight = 100) + { + lock (_locko) + { + if (_isStopping) return false; + install?.Invoke(); + if (release != null) + _callbacks.Add(new KeyValuePair(weight, release)); + return true; + } + } + + public void Stop() + { + lock (_locko) + { + if (_isStopping) return; + if (IsMainDom == false) return; // probably not needed + _isStopping = true; + } + + try + { + foreach (var callback in _callbacks.OrderBy(x => x.Key).Select(x => x.Value)) + { + callback(); // no timeout on callbacks + } + } + finally + { + // in any case... + IsMainDom = false; + } + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 9132df3c67..323fc49543 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -329,6 +329,7 @@ + @@ -1431,6 +1432,7 @@ + diff --git a/src/Umbraco.Examine/MediaValueSetBuilder.cs b/src/Umbraco.Examine/MediaValueSetBuilder.cs index 8df51570c1..f0e5e895e6 100644 --- a/src/Umbraco.Examine/MediaValueSetBuilder.cs +++ b/src/Umbraco.Examine/MediaValueSetBuilder.cs @@ -14,7 +14,7 @@ namespace Umbraco.Examine private readonly IUserService _userService; public MediaValueSetBuilder(PropertyEditorCollection propertyEditors, - IEnumerable urlSegmentProviders, + UrlSegmentProviderCollection urlSegmentProviders, IUserService userService) : base(propertyEditors, false) { diff --git a/src/Umbraco.Tests/Composing/LightInjectValidation.cs b/src/Umbraco.Tests/Composing/LightInjectValidation.cs index ea603a29f2..75062e613c 100644 --- a/src/Umbraco.Tests/Composing/LightInjectValidation.cs +++ b/src/Umbraco.Tests/Composing/LightInjectValidation.cs @@ -136,8 +136,8 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h { var serviceType = validationTarget.ServiceType.GenericTypeArguments[0]; var underlyingvalidationTarget = validationTarget.WithServiceDescription(serviceType, string.Empty); - registration = GetServiceRegistration(serviceMap, underlyingvalidationTarget); - if (registration != null) return; + var registrations = GetServiceRegistrations(serviceMap, underlyingvalidationTarget); + if (registrations.Any()) return; // strict: there has to be at least 1 string message = string.Format(MissingDeferredDependency, validationTarget.ServiceType, underlyingvalidationTarget.ServiceType); @@ -198,9 +198,13 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h LifeSpans.TryAdd(typeof(TLifetime), lifeSpan); } + private static IEnumerable GetServiceRegistrations(ServiceMap serviceMap, ValidationTarget validationTarget) + { + return serviceMap.Where(x => validationTarget.ServiceType.IsAssignableFrom(x.Key)).SelectMany(x => x.Value.Values); + } + private static ServiceRegistration GetServiceRegistration(ServiceMap serviceMap, ValidationTarget validationTarget) { - if (!serviceMap.TryGetValue(validationTarget.ServiceType, out var registrations)) { return null; @@ -224,8 +228,6 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h return null; } - - private static string GetLifetimeName(ILifetime lifetime) { if (lifetime == null) @@ -235,7 +237,6 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h return lifetime.GetType().Name; } - private static int GetLifespan(ILifetime lifetime) { if (lifetime == null) @@ -248,9 +249,6 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h } return 0; } - - - } diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 4d3a315cd2..91af6ebeb6 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -22,6 +22,7 @@ namespace Umbraco.Tests.Runtimes public class StandaloneTests { [Test] + [Explicit("This test must be run manually")] public void Test() { // this is almost what CoreRuntime does, without @@ -53,9 +54,12 @@ namespace Umbraco.Tests.Runtimes // at that point, CoreRuntime also does //composition.RegisterUnique(mainDom) // we should make it - //composition.RegisterUnique(mainDom) + composition.RegisterUnique(Mock.Of()); + //composition.RegisterUnique(new SimpleMainDom()); // because some components want to use it // (and then, what would a standalone maindom be?) + // + // is this an essential thing then?? // get the components // all of them? @@ -84,13 +88,13 @@ namespace Umbraco.Tests.Runtimes // and then, validate var lightInjectContainer = (LightInject.ServiceContainer) factory.Concrete; var results = lightInjectContainer.Validate().ToList(); - foreach (var resultGroup in results.GroupBy(x => x.Severity)) + foreach (var resultGroup in results.GroupBy(x => x.Severity).OrderBy(x => x.Key)) foreach (var result in resultGroup) { Console.WriteLine(); Console.WriteLine($"{result.Severity}: {WordWrap(result.Message, 120)}"); var target = result.ValidationTarget; - Console.Write("\t"); + Console.Write("\tsvce: "); Console.Write(target.ServiceName); Console.Write(target.DeclaringService.ServiceType); if (!target.DeclaringService.ServiceName.IsNullOrWhiteSpace()) @@ -100,13 +104,15 @@ namespace Umbraco.Tests.Runtimes Console.Write("'"); } - Console.Write(" "); + Console.Write(" ("); if (target.DeclaringService.Lifetime == null) Console.Write("?"); else Console.Write(target.DeclaringService.Lifetime.ToString().TrimStart("LightInject.")); - Console.WriteLine(); - Console.Write("\t"); + Console.WriteLine(")"); + Console.Write("\timpl: "); + Console.WriteLine(target.DeclaringService.ImplementingType); + Console.Write("\tparm: "); Console.Write(target.Parameter); Console.WriteLine(); } diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 13f85549f1..cb36e6ca5f 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -91,7 +91,7 @@ namespace Umbraco.Tests.TestHelpers IGlobalSettings globalSettings, IUmbracoSettingsSection umbracoSettings, IEventMessagesFactory eventMessagesFactory, - IEnumerable urlSegmentProviders, + UrlSegmentProviderCollection urlSegmentProviders, TypeLoader typeLoader, IFactory factory = null) { diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index d39ececca7..09ad340e2b 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -44,7 +44,7 @@ namespace Umbraco.Tests.UmbracoExamine public static MediaIndexPopulator GetMediaIndexRebuilder(PropertyEditorCollection propertyEditors, IMediaService mediaService) { - var mediaValueSetBuilder = new MediaValueSetBuilder(propertyEditors, new[] { new DefaultUrlSegmentProvider() }, GetMockUserService()); + var mediaValueSetBuilder = new MediaValueSetBuilder(propertyEditors, new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() }), GetMockUserService()); var mediaIndexDataSource = new MediaIndexPopulator(null, mediaService, mediaValueSetBuilder); return mediaIndexDataSource; } @@ -161,7 +161,7 @@ namespace Umbraco.Tests.UmbracoExamine if (validator == null) validator = new ContentValueSetValidator(true); - + var i = new UmbracoContentIndex( "testIndexer", UmbracoExamineIndex.UmbracoIndexFieldDefinitions, diff --git a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs index 760e966435..b848425736 100644 --- a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs @@ -2,6 +2,7 @@ using Umbraco.Core.Composing; using Umbraco.Web.Install; using Umbraco.Web.Install.InstallSteps; +using Umbraco.Web.Install.Models; namespace Umbraco.Web.Composing.Composers { diff --git a/src/Umbraco.Web/Macros/PartialViewMacroController.cs b/src/Umbraco.Web/Macros/PartialViewMacroController.cs index 9437c8c36d..21d7b3292c 100644 --- a/src/Umbraco.Web/Macros/PartialViewMacroController.cs +++ b/src/Umbraco.Web/Macros/PartialViewMacroController.cs @@ -2,14 +2,16 @@ using Umbraco.Web.Models; using Umbraco.Web.Mvc; using System.Linq; +using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Web.Macros { /// - /// Controller to render macro content for Parital View Macros + /// Controller to render macro content for Partial View Macros /// [MergeParentContextViewData] + [HideFromTypeFinder] // explicitly used: do *not* find and register it! internal class PartialViewMacroController : Controller { private readonly MacroModel _macro; diff --git a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs index 0e4b902196..f64121e09a 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs @@ -37,15 +37,6 @@ namespace Umbraco.Web.Models.Mapping _userService = userService ?? throw new System.ArgumentNullException(nameof(userService)); } - public MemberTabsAndPropertiesResolver(IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService localizedTextService, IEnumerable ignoreProperties, IMemberService memberService, IUserService userService) - : base(localizedTextService, ignoreProperties) - { - _umbracoContextAccessor = umbracoContextAccessor ?? throw new System.ArgumentNullException(nameof(umbracoContextAccessor)); - _localizedTextService = localizedTextService ?? throw new System.ArgumentNullException(nameof(localizedTextService)); - _memberService = memberService ?? throw new System.ArgumentNullException(nameof(memberService)); - _userService = userService ?? throw new System.ArgumentNullException(nameof(userService)); - } - /// /// Overriden to deal with custom member properties and permissions. public override IEnumerable> Resolve(IMember source, MemberDisplay destination, IEnumerable> destMember, ResolutionContext context) diff --git a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs index 7bbdb85549..ab33c3886b 100644 --- a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Models.Mapping IgnoreProperties = ignoreProperties ?? throw new ArgumentNullException(nameof(ignoreProperties)); } - //TODO: This should deserialize to ListViewConfiguration + //TODO: This should deserialize to ListViewConfiguration private static int GetTabNumberFromConfig(IDictionary listViewConfig) { if (!listViewConfig.TryGetValue("displayAtTabNumber", out var displayTabNum)) @@ -139,13 +139,7 @@ namespace Umbraco.Web.Models.Mapping { public TabsAndPropertiesResolver(ILocalizedTextService localizedTextService) : base(localizedTextService) - { - } - - public TabsAndPropertiesResolver(ILocalizedTextService localizedTextService, IEnumerable ignoreProperties) - : base(localizedTextService, ignoreProperties) - { - } + { } public virtual IEnumerable> Resolve(TSource source, TDestination destination, IEnumerable> destMember, ResolutionContext context) { diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index 100833216e..e97fa16266 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -79,7 +79,7 @@ namespace Umbraco.Web.PublishedCache.NuCache //private static int _singletonCheck; - public PublishedSnapshotService(Options options, MainDom mainDom, IRuntimeState runtime, + public PublishedSnapshotService(Options options, IMainDom mainDom, IRuntimeState runtime, ServiceContext serviceContext, IPublishedContentTypeFactory publishedContentTypeFactory, IdkMap idkMap, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, ILogger logger, IScopeProvider scopeProvider, diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index bfaf9a8121..263b97dd0d 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -40,8 +40,7 @@ namespace Umbraco.Web.Routing IContentLastChanceFinder contentLastChanceFinder, IVariationContextAccessor variationContextAccessor, ServiceContext services, - IProfilingLogger proflog, - Func> getRolesForLogin = null) + IProfilingLogger proflog) { _webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection)); _contentFinders = contentFinders ?? throw new ArgumentNullException(nameof(contentFinders)); @@ -51,7 +50,7 @@ namespace Umbraco.Web.Routing _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _logger = proflog; - GetRolesForLogin = getRolesForLogin ?? (s => Roles.Provider.GetRolesForUser(s)); + GetRolesForLogin = s => Roles.Provider.GetRolesForUser(s); } // fixme