diff --git a/src/core/Elsa.Core/Extensions/ElsaOptionBuilderExtensions.cs b/src/core/Elsa.Core/Extensions/ElsaOptionBuilderExtensions.cs index 241b99726..cbf7068d7 100644 --- a/src/core/Elsa.Core/Extensions/ElsaOptionBuilderExtensions.cs +++ b/src/core/Elsa.Core/Extensions/ElsaOptionBuilderExtensions.cs @@ -12,11 +12,19 @@ namespace Elsa { public static ElsaOptionsBuilder AddFeatures(this ElsaOptionsBuilder builder, IEnumerable assemblyMarkerTypes, IConfiguration configuration) => AddFeatures(builder, GetAssemblies(assemblyMarkerTypes), configuration); + /// + /// Parse all features from the appsettings.json, filter only enabled features, + /// find all start up classes with matching attribute and create their instances. + /// + /// ElsaOptionsBuilder + /// Available assembly collection + /// IConfiguration + /// ElsaOptionsBuilder public static ElsaOptionsBuilder AddFeatures(this ElsaOptionsBuilder builder, IEnumerable assemblies, IConfiguration configuration) { var enabledFeatures = ParseFeatures(configuration); - if (enabledFeatures == null!) // Null when configuration binding finds an empty array. + if (enabledFeatures == null!) return builder; enabledFeatures = enabledFeatures.ToHashSet(); @@ -40,6 +48,11 @@ namespace Elsa return builder; } + /// + /// Parse all features from the appsettings.json and popualte enabled feature collection + /// + /// IConfiguration + /// Enabled feature collection private static IEnumerable ParseFeatures(IConfiguration configuration) { var elsaFeaturesSection = "Elsa:Features"; @@ -48,7 +61,7 @@ namespace Elsa foreach (var feature in features) { - var featureOptions = ParseFeatureFlag(configuration, feature.Key); + var featureOptions = ParseFeatureSection(configuration, feature.Key); if (!featureOptions.Enabled) continue; var key = feature.Key.Replace($"{elsaFeaturesSection}:", string.Empty); @@ -63,6 +76,88 @@ namespace Elsa return enabledFeatures; } + /// + /// Parse single feature section from the appsettings.json and popualte feature model + /// + /// IConfiguration + /// Feature name + /// Populated feature model + private static FeatureModel ParseFeatureSection(IConfiguration configuration, string feature) + { + var featureModel = new FeatureModel(); + + if (configuration.GetSection($"{feature}:Enabled").Exists()) + { + var featureItems = configuration.GetSection($"{feature}").AsEnumerable(); + + ParseFeatureItems(feature, featureModel, featureItems); + ParseFeatureOptions(configuration, feature, featureModel); + + return featureModel; + } + + if (!feature.EndsWith(":Enabled")) + { + bool.TryParse(configuration.GetValue($"{feature}"), out var enabled); + featureModel.Enabled = enabled; + } + return featureModel; + } + + /// + /// Parse feature section key/value collection except Enabled and Options keys from the appsetting.json and popualte feature model + /// + /// Feature name + /// Feature model + /// Feature section kay/value collection + private static void ParseFeatureItems(string feature, FeatureModel featureModel, IEnumerable> featureItems) + { + featureModel.Items = new Dictionary(); + + foreach (var featureItem in featureItems) + { + if (featureItem.Value == null) continue; + + var itemKey = featureItem.Key.Replace($"{feature}:", string.Empty); + + if (itemKey.Contains(":")) continue; + + if (itemKey == "Enabled") + { + bool.TryParse(featureItem.Value, out var enabled); + featureModel.Enabled = enabled; + } + else + { + featureModel.Items.Add(itemKey, featureItem.Value); + } + } + } + + /// + /// Parse feature Options section from the appsetting.json and populate feature model + /// + /// IConfiguration + /// Feature name + /// Feature model + private static void ParseFeatureOptions(IConfiguration configuration, string feature, FeatureModel featureModel) + { + if (configuration.GetSection($"{feature}:Options").Exists()) + { + var options = new Dictionary(); + configuration.GetSection($"{feature}:Options").Bind(options); + featureModel.Options = options; + } + } + + /// + /// Permutate all possible order combinations in Feature section key/value collection + /// + /// Feature name + /// Feature values array to permutate + /// Enabled feature collection + /// Start index + /// End index private static void GetPermutations(string feature, string[] values, ICollection enabledFeatures, int start, int end) { if (start == end) @@ -83,6 +178,11 @@ namespace Elsa } } + /// + /// Swap two string values + /// + /// + /// private static void Swap(ref string item1, ref string item2) { if (item1 == item2) return; @@ -92,62 +192,13 @@ namespace Elsa item2 = temp; } - private static FeatureOptions ParseFeatureFlag(IConfiguration configuration, string feature) - { - var featureOptions = new FeatureOptions(); - - if (configuration.GetSection($"{feature}:Enabled").Exists()) - { - var featureItems = configuration.GetSection($"{feature}").AsEnumerable(); - - ParseFeatureItems(feature, featureOptions, featureItems); - ParseFeatureOptions(configuration, feature, featureOptions); - - return featureOptions; - } - - if (!feature.EndsWith(":Enabled")) - { - bool.TryParse(configuration.GetValue($"{feature}"), out var enabled); - featureOptions.Enabled = enabled; - } - return featureOptions; - } - - private static void ParseFeatureItems(string feature, FeatureOptions featureOptions, IEnumerable> featureItems) - { - featureOptions.Items = new Dictionary(); - - foreach (var featureItem in featureItems) - { - if (featureItem.Value == null) continue; - - var itemKey = featureItem.Key.Replace($"{feature}:", string.Empty); - - if (itemKey.Contains(":")) continue; - - if (itemKey == "Enabled") - { - bool.TryParse(featureItem.Value, out var enabled); - featureOptions.Enabled = enabled; - } - else - { - featureOptions.Items.Add(itemKey, featureItem.Value); - } - } - } - - private static void ParseFeatureOptions(IConfiguration configuration, string feature, FeatureOptions featureOptions) - { - if (configuration.GetSection($"{feature}:Options").Exists()) - { - var options = new Dictionary(); - configuration.GetSection($"{feature}:Options").Bind(options); - featureOptions.Options = options; - } - } - private static IEnumerable GetAssemblies(IEnumerable assemblyMarkerTypes) => assemblyMarkerTypes.Select(x => x.Assembly).Distinct(); + + private class FeatureModel + { + public bool Enabled { get; set; } + public Dictionary? Items { get; set; } + public Dictionary? Options { get; set; } + } } } \ No newline at end of file diff --git a/src/core/Elsa.Core/FeatureOptions.cs b/src/core/Elsa.Core/FeatureOptions.cs deleted file mode 100644 index 8be485f63..000000000 --- a/src/core/Elsa.Core/FeatureOptions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace Elsa -{ - public class FeatureOptions - { - public bool Enabled { get; set; } - public Dictionary? Items { get; set; } - public Dictionary? Options { get; set; } - } -}