From 9590b5070045dce56e7d8660a871cb8a65d3e4e6 Mon Sep 17 00:00:00 2001 From: Yaroslav-B <91521756+Yaroslav-B@users.noreply.github.com> Date: Mon, 1 May 2023 19:05:25 +0300 Subject: [PATCH 1/8] feat: add FeatureHolder --- ManagedCode.FeatureChecker/FeatureHolder.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 ManagedCode.FeatureChecker/FeatureHolder.cs diff --git a/ManagedCode.FeatureChecker/FeatureHolder.cs b/ManagedCode.FeatureChecker/FeatureHolder.cs new file mode 100644 index 0000000..b0049e0 --- /dev/null +++ b/ManagedCode.FeatureChecker/FeatureHolder.cs @@ -0,0 +1,15 @@ +using System.Collections.Immutable; + +namespace ManagedCode.FeatureChecker; +public class FeatureHolder +{ + public readonly Dictionary _features; + + public ImmutableDictionary Features => + _features.ToImmutableDictionary(); + + public FeatureHolder() + { + _features = new Dictionary(); + } +} From d918f212c920ed437d114f749f18564531b78614 Mon Sep 17 00:00:00 2001 From: Yaroslav-B <91521756+Yaroslav-B@users.noreply.github.com> Date: Mon, 1 May 2023 19:24:18 +0300 Subject: [PATCH 2/8] feat: remove obsolete members of FeatureChecker and Feature model --- ManagedCode.FeatureChecker/Feature.cs | 6 -- ManagedCode.FeatureChecker/FeatureChecker.cs | 94 ++------------------ 2 files changed, 7 insertions(+), 93 deletions(-) delete mode 100644 ManagedCode.FeatureChecker/Feature.cs diff --git a/ManagedCode.FeatureChecker/Feature.cs b/ManagedCode.FeatureChecker/Feature.cs deleted file mode 100644 index bb59474..0000000 --- a/ManagedCode.FeatureChecker/Feature.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ManagedCode.FeatureChecker; -public class Feature -{ - public string Name { get; set; } = null!; - public FeatureStatus Status { get; set; } -} diff --git a/ManagedCode.FeatureChecker/FeatureChecker.cs b/ManagedCode.FeatureChecker/FeatureChecker.cs index 40c5b95..b805b66 100644 --- a/ManagedCode.FeatureChecker/FeatureChecker.cs +++ b/ManagedCode.FeatureChecker/FeatureChecker.cs @@ -1,99 +1,23 @@ -namespace ManagedCode.FeatureChecker; +using System.Collections.Immutable; + +namespace ManagedCode.FeatureChecker; public class FeatureChecker { - private readonly Dictionary _features; + private readonly ImmutableDictionary _features; - public FeatureChecker() + public FeatureChecker(FeatureHolder featureHolder) { - _features = new Dictionary(); + _features = featureHolder.Features; } - public event EventHandler FeatureAdded; - public event EventHandler FeatureRemoved; - public event EventHandler FeatureStatusChanged; - - - public bool TryAddFeature(string name, FeatureStatus status) - { - var feature = new Feature() - { - Name = name, - Status = status - }; - - return TryAddFeature(feature); - } - - public bool TryAddFeature(Feature newFeature) - { - ThrowIfNull(newFeature, nameof(newFeature)); - ValidateModel(newFeature); - - return _features.TryAdd(newFeature.Name, newFeature); - } - - - public void RemoveFeature(string name) - { - ThrowIfNullOrEmpty(name, nameof(name)); - _features.Remove(name); - } - - public void RemoveAllFeatures() => _features.Clear(); - - public bool IsFeatureExists(string name) { ThrowIfNullOrEmpty(name, nameof(name)); return _features.ContainsKey(name); } - - public bool TryGetFeatureStatus(string name, out FeatureStatus status) - { - var result = TryGetFeatureByName(name, out Feature? feature); - status = feature?.Status ?? default; - - return result; - } - - public bool TryGetFeatureByName(string name, out Feature? feature) - { - ThrowIfNullOrEmpty(name, nameof(name)); - - return _features.TryGetValue(name, out feature); - } - - - public Feature[] GetExistFeatures() => _features.Values.ToArray(); - - public IEnumerable GetFeaturesByStatus(FeatureStatus status) - { - return _features.Values.Where(x => x.Status == status); - } - - - public bool TryUpdateFeatureStatus(string name, FeatureStatus status) - { - var result = TryGetFeatureByName(name, out Feature? feature); - - if(result && feature != null) - { - feature.Status = FeatureStatus.Disabled; - } - - return result; - } - - - private static void ThrowIfNull(object obj, string paramName) - { - if(obj == null) - { - throw new ArgumentNullException(paramName, $"Parameter is null."); - } - } + private static void ThrowIfNullOrEmpty(string arg, string argName) { @@ -103,8 +27,4 @@ private static void ThrowIfNullOrEmpty(string arg, string argName) } } - private static void ValidateModel(Feature feature) - { - //do some validation - } } From f7870e0752ffc671391f5f67d40b7a669e55b040 Mon Sep 17 00:00:00 2001 From: Yaroslav-B <91521756+Yaroslav-B@users.noreply.github.com> Date: Mon, 1 May 2023 20:03:10 +0300 Subject: [PATCH 3/8] feat: add main functions --- ManagedCode.FeatureChecker/FeatureChecker.cs | 32 +++++++++++---- ManagedCode.FeatureChecker/FeatureHolder.cs | 42 +++++++++++++++++++- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/ManagedCode.FeatureChecker/FeatureChecker.cs b/ManagedCode.FeatureChecker/FeatureChecker.cs index b805b66..79569d3 100644 --- a/ManagedCode.FeatureChecker/FeatureChecker.cs +++ b/ManagedCode.FeatureChecker/FeatureChecker.cs @@ -6,6 +6,8 @@ public class FeatureChecker { private readonly ImmutableDictionary _features; + public int Count => _features.Count; + public FeatureChecker(FeatureHolder featureHolder) { _features = featureHolder.Features; @@ -13,18 +15,32 @@ public FeatureChecker(FeatureHolder featureHolder) public bool IsFeatureExists(string name) { - ThrowIfNullOrEmpty(name, nameof(name)); + return ValidateFeatureName(name) + ? _features.ContainsKey(name) + : false; + } + + public bool TryGetFeatureStatus(string name, out FeatureStatus status) + { + status = default; - return _features.ContainsKey(name); + return ValidateFeatureName(name) + ? _features.TryGetValue(name, out status) + : false; } - - private static void ThrowIfNullOrEmpty(string arg, string argName) + public List GetFeaturesByStatus(FeatureStatus status) + { + return _features + .Where(x => x.Value == status) + .Select(x => x.Key) + .ToList(); + } + + + private bool ValidateFeatureName(string featureName) { - if(string.IsNullOrWhiteSpace(arg)) - { - throw new ArgumentException($"Invalid parameter '{argName}': {arg}."); - } + return !string.IsNullOrWhiteSpace(featureName); } } diff --git a/ManagedCode.FeatureChecker/FeatureHolder.cs b/ManagedCode.FeatureChecker/FeatureHolder.cs index b0049e0..862c72b 100644 --- a/ManagedCode.FeatureChecker/FeatureHolder.cs +++ b/ManagedCode.FeatureChecker/FeatureHolder.cs @@ -1,4 +1,5 @@ -using System.Collections.Immutable; +using System.Collections.Generic; +using System.Collections.Immutable; namespace ManagedCode.FeatureChecker; public class FeatureHolder @@ -12,4 +13,43 @@ public FeatureHolder() { _features = new Dictionary(); } + + public bool TryAddFeature(string featureName, FeatureStatus status) + { + return ValidateFeatureName(featureName) + ? _features.TryAdd(featureName, status) + : false; + } + + public bool TryGetFeatureStatus(string featureName, out FeatureStatus status) + { + status = default; + + return ValidateFeatureName(featureName) + ? _features.TryGetValue(featureName, out status) + : false; + } + + public bool TryRemoveFeature(string featureName) + { + return ValidateFeatureName(featureName) + ? _features.Remove(featureName) + : false; + } + + public void UpdateFeatureStatus(string featureName, FeatureStatus status) + { + if(!ValidateFeatureName(featureName)) + { + return; + } + + _features[featureName] = status; + } + + + private bool ValidateFeatureName(string featureName) + { + return !string.IsNullOrWhiteSpace(featureName); + } } From 487e0500163c5d626161ed135f587e4cc0772f49 Mon Sep 17 00:00:00 2001 From: Yaroslav-B <91521756+Yaroslav-B@users.noreply.github.com> Date: Tue, 2 May 2023 13:23:24 +0300 Subject: [PATCH 4/8] fix: fix typo in FeautureStatus enum --- ManagedCode.FeatureChecker/FeatureStatus.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ManagedCode.FeatureChecker/FeatureStatus.cs b/ManagedCode.FeatureChecker/FeatureStatus.cs index 46edc00..00bfba5 100644 --- a/ManagedCode.FeatureChecker/FeatureStatus.cs +++ b/ManagedCode.FeatureChecker/FeatureStatus.cs @@ -3,6 +3,6 @@ public enum FeatureStatus { Disabled, - Eanabled, + Enabled, Debug, } From 32309c12f34ad7f5a6b5be686c9e916b318cfb30 Mon Sep 17 00:00:00 2001 From: Yaroslav-B <91521756+Yaroslav-B@users.noreply.github.com> Date: Tue, 2 May 2023 13:35:18 +0300 Subject: [PATCH 5/8] chore: update project file to support .net standard 2.1 --- .../ManagedCode.FeatureChecker.csproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ManagedCode.FeatureChecker/ManagedCode.FeatureChecker.csproj b/ManagedCode.FeatureChecker/ManagedCode.FeatureChecker.csproj index 5f33f2c..f2075a7 100644 --- a/ManagedCode.FeatureChecker/ManagedCode.FeatureChecker.csproj +++ b/ManagedCode.FeatureChecker/ManagedCode.FeatureChecker.csproj @@ -1,4 +1,4 @@ - + enable @@ -15,7 +15,9 @@ managedcode, Tests, Detector, TestsDetector, unit tests - + + + From 0344eeabb53f9039541218b069ae8166c382a4da Mon Sep 17 00:00:00 2001 From: Yaroslav-B <91521756+Yaroslav-B@users.noreply.github.com> Date: Tue, 2 May 2023 14:07:02 +0300 Subject: [PATCH 6/8] feat: change FeatureHolder to support serialization with Text.Json --- ManagedCode.FeatureChecker/FeatureHolder.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ManagedCode.FeatureChecker/FeatureHolder.cs b/ManagedCode.FeatureChecker/FeatureHolder.cs index 862c72b..8742d0e 100644 --- a/ManagedCode.FeatureChecker/FeatureHolder.cs +++ b/ManagedCode.FeatureChecker/FeatureHolder.cs @@ -1,13 +1,18 @@ -using System.Collections.Generic; -using System.Collections.Immutable; +using System.Collections.Immutable; +using System.Text.Json.Serialization; namespace ManagedCode.FeatureChecker; public class FeatureHolder { - public readonly Dictionary _features; + private Dictionary _features; + + [JsonInclude] + public ImmutableDictionary Features + { + get => _features.ToImmutableDictionary(); + private set => _features = new Dictionary(value); + } - public ImmutableDictionary Features => - _features.ToImmutableDictionary(); public FeatureHolder() { From 61f91a9c9c10356a40819765dad9bb94f831e421 Mon Sep 17 00:00:00 2001 From: Yaroslav-B <91521756+Yaroslav-B@users.noreply.github.com> Date: Tue, 2 May 2023 16:03:08 +0300 Subject: [PATCH 7/8] doc: update readme.md, add usage --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.md b/README.md index 52f0cc7..cc922d6 100644 --- a/README.md +++ b/README.md @@ -1 +1,40 @@ # FeatureChecker + +## Usage + +```js + var holder = new FeatureHolder(); + + holder.TryAddFeature("feature 1", default); + holder.TryAddFeature("feature 2", FeatureStatus.Enabled); + holder.TryAddFeature("feature 3", FeatureStatus.Debug); + + holder.UpdateFeatureStatus("feature 3", FeatureStatus.Enabled); + + + var checker = new FeatureChecker(holder); + + if(checker.IsFeatureExists("feature_name")) + { + //do some things... + } + + + var enabledFeatures = checker.GetFeaturesByStatus(FeatureStatus.Enabled); + + foreach(var feat in enabledFeatures) + { + Console.WriteLine(feat); + //other code... + } + + + bool result = checker.TryGetFeatureStatus("myFeature", out FeatureStatus status); + + if(result) + { + Console.WriteLine(status); + //other code... + } + +``` \ No newline at end of file From b48d0d334fffa053cabf03b47bf576644b30b83e Mon Sep 17 00:00:00 2001 From: Yaroslav-B <91521756+Yaroslav-B@users.noreply.github.com> Date: Tue, 2 May 2023 16:12:38 +0300 Subject: [PATCH 8/8] feat: change feature removing in FeatureHolder change RemoveFeature method signature rename the method --- ManagedCode.FeatureChecker/FeatureHolder.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ManagedCode.FeatureChecker/FeatureHolder.cs b/ManagedCode.FeatureChecker/FeatureHolder.cs index 8742d0e..a11ed60 100644 --- a/ManagedCode.FeatureChecker/FeatureHolder.cs +++ b/ManagedCode.FeatureChecker/FeatureHolder.cs @@ -35,11 +35,12 @@ public bool TryGetFeatureStatus(string featureName, out FeatureStatus status) : false; } - public bool TryRemoveFeature(string featureName) + public void RemoveFeature(string featureName) { - return ValidateFeatureName(featureName) - ? _features.Remove(featureName) - : false; + if(ValidateFeatureName(featureName)) + { + _features.Remove(featureName); + } } public void UpdateFeatureStatus(string featureName, FeatureStatus status)