diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationCollection.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationCollection.cs index 3441227ad0..9e16466fa4 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationCollection.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleConfigurationCollection.cs @@ -1,68 +1,127 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using JetBrains.Annotations; namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling { public class BundleConfigurationCollection { - private readonly ConcurrentDictionary _bundleContributors; + private readonly ConcurrentDictionary _bundles; + private readonly ConcurrentDictionary>> _lazyBundleConfigurationActions; public BundleConfigurationCollection() { - _bundleContributors = new ConcurrentDictionary(); + _bundles = new ConcurrentDictionary(); + _lazyBundleConfigurationActions = new ConcurrentDictionary>>(); } - public BundleConfiguration Add(string bundleName) + /// + /// Adds a new bundle with given . + /// Throws if there is already a bundle with the same name. + /// + /// Bundle name. + /// Initial configuration action. + /// Returns this object for chained calls. + public BundleConfigurationCollection Add([NotNull] string bundleName, [CanBeNull] Action configureAction = null) { - if (_bundleContributors.ContainsKey(bundleName)) + if (!TryAdd(bundleName, configureAction)) { throw new AbpException($"There is already a bundle added with given {nameof(bundleName)}: {bundleName}"); } - return _bundleContributors.AddOrUpdate(bundleName, new BundleConfiguration(bundleName), (n, c) => c); + return this; } - public BundleConfiguration Get(string bundleName) + /// + /// Tries to add a new bundle with given . + /// Returns false if it's already created before. + /// is not called if it's already added before. + /// + /// Bundle name. + /// Initial configuration action. + /// Returns true if added. Returns false if it's already added before. + public bool TryAdd([NotNull] string bundleName, [CanBeNull] Action configureAction = null) { - CheckBundle(bundleName); + Check.NotNull(bundleName, nameof(bundleName)); - return _bundleContributors[bundleName]; - } + if (_bundles.ContainsKey(bundleName)) + { + return false; + } - public BundleConfiguration GetOrNull(string bundleName) - { - if (!_bundleContributors.TryGetValue(bundleName, out var bundleConfiguration)) + var bundle = new BundleConfiguration(bundleName); + configureAction?.Invoke(bundle); + + if (_lazyBundleConfigurationActions.TryGetValue(bundleName, out var configurationActions)) { - return null; + lock (configurationActions) + { + configurationActions.ForEach(c => c.Invoke(bundle)); + } } - return bundleConfiguration; - } + if (!_bundles.TryAdd(bundleName, bundle)) + { + return false; + } - public BundleConfiguration GetOrAdd(string bundleName) - { - return GetOrAdd(bundleName, c => { }); + if (configurationActions != null) + { + lock (configurationActions) + { + configurationActions.Clear(); + } + } + + return true; } - internal BundleConfiguration GetOrAdd(string bundleName, Action configureAction) + /// + /// Configures an existing bundle. + /// This method also works for lazy bundles (those are created using razor tag helpers). + /// + /// Bundle name + /// Configure action + /// Returns this object for chained calls. + public BundleConfigurationCollection Configure([NotNull] string bundleName, [NotNull] Action configureAction) { - return _bundleContributors.GetOrAdd( - bundleName, - () => + Check.NotNull(bundleName, nameof(bundleName)); + Check.NotNull(configureAction, nameof(configureAction)); + + if (_bundles.TryGetValue(bundleName, out var bundle)) + { + configureAction.Invoke(bundle); + } + else + { + var configurationActions = _lazyBundleConfigurationActions + .GetOrAdd(bundleName, () => new List>()); + + lock (configurationActions) { - var configuration = new BundleConfiguration(bundleName); - configureAction.Invoke(configuration); - return configuration; - }); + configurationActions.Add(configureAction); + } + } + + return this; } - private void CheckBundle(string bundleName) + /// + /// Gets a bundle. + /// + /// The bundle name + /// The bundle configuration + public BundleConfiguration Get([NotNull] string bundleName) { - if (!_bundleContributors.ContainsKey(bundleName)) + Check.NotNull(bundleName, nameof(bundleName)); + + if (!_bundles.TryGetValue(bundleName, out var bundle)) { throw new AbpException($"There is no bundle with given {nameof(bundleName)}: {bundleName}"); } + + return bundle; } } } \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs index 3732a7cffd..30c78ff469 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs @@ -139,12 +139,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling public virtual void CreateStyleBundle(string bundleName, Action configureAction) { - _options.StyleBundles.GetOrAdd(bundleName, configureAction); + _options.StyleBundles.TryAdd(bundleName, configureAction); } public virtual void CreateScriptBundle(string bundleName, Action configureAction) { - _options.ScriptBundles.GetOrAdd(bundleName, configureAction); + _options.ScriptBundles.TryAdd(bundleName, configureAction); } protected virtual bool IsBundlingEnabled() diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs index 2c24cc725d..a929a0c358 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs @@ -25,13 +25,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared { options .StyleBundles - .Add(StandardBundles.Styles.Global) - .AddContributors(typeof(SharedThemeGlobalStyleContributor)); + .Add(StandardBundles.Styles.Global, bundle => { bundle.AddContributors(typeof(SharedThemeGlobalStyleContributor)); }); options .ScriptBundles - .Add(StandardBundles.Scripts.Global) - .AddContributors(typeof(SharedThemeGlobalScriptContributor)); + .Add(StandardBundles.Scripts.Global, bundle => bundle.AddContributors(typeof(SharedThemeGlobalScriptContributor))); }); services.AddAssemblyOf();