From f600ee7d2d1ba5ade96d39e22cac0de639f69920 Mon Sep 17 00:00:00 2001 From: Geovanni Perez Date: Mon, 12 Mar 2018 10:37:21 -0600 Subject: [PATCH] Get flag names (#98) * Add GetFlagNames method * Add EnumCache class * Add cache to EnumHelper * Remove EnumHelper from Runtime and fix some issues * Versioning --- .../Components/EnumHelper.cs | 184 +++++++++++------- src/Unosquare.Swan.Lite/Runtime.cs | 6 +- .../Unosquare.Swan.Lite.csproj | 2 +- src/Unosquare.Swan/Unosquare.Swan.csproj | 2 +- test/Unosquare.Swan.Test/EnumHelperTest.cs | 35 ++-- test/Unosquare.Swan.Test/Mocks/JsonMock.cs | 2 +- 6 files changed, 139 insertions(+), 92 deletions(-) diff --git a/src/Unosquare.Swan.Lite/Components/EnumHelper.cs b/src/Unosquare.Swan.Lite/Components/EnumHelper.cs index 41d79887d..0fda2b3f1 100644 --- a/src/Unosquare.Swan.Lite/Components/EnumHelper.cs +++ b/src/Unosquare.Swan.Lite/Components/EnumHelper.cs @@ -3,22 +3,29 @@ using System; using System.Collections.Generic; using System.Linq; + using Abstractions; /// /// Provide Enumerations helpers with internal cache /// - public static class EnumHelper + public class EnumHelper + : SingletonBase>> { - private static readonly Dictionary[]> ValueCache = - new Dictionary[]>(); - - private static readonly Dictionary[]> IndexCache = - new Dictionary[]>(); - - private static readonly Dictionary ArrayValueCache = - new Dictionary(); + /// + /// Gets all the names and enumerators from a specific Enum type + /// + /// The type of the attribute to be retrieved + /// A tuple of enumarator names and their value stored for the specified type + public static Tuple[] Retrieve() + where T : struct, IConvertible + { + return Instance.Retrieve(typeof(T), () => + { + var values = Enum.GetValues(typeof(T)).Cast(); - private static readonly object LockObject = new object(); + return values.Select(item => new Tuple(Enum.GetName(typeof(T), item), item)).ToList(); + }); + } /// /// Gets the cached items with the enum item value. @@ -30,68 +37,49 @@ public static class EnumHelper /// that represents items with the enum item value /// public static Tuple[] GetItemsWithValue(bool humanize = true) + where T : struct, IConvertible { - lock (LockObject) - { - var tupleName = typeof(T); - - if (ValueCache.ContainsKey(tupleName) == false) - { - ValueCache.Add(tupleName, Enum.GetNames(tupleName) - .Select(x => - new Tuple((int) Enum.Parse(tupleName, x), humanize ? x.Humanize() : x)) - .ToArray()); - } - - return ValueCache[tupleName]; - } + return Retrieve() + .Select(x => new Tuple((int) x.Item2, humanize ? x.Item1.Humanize() : x.Item1)) + .ToArray(); } /// - /// Gets the cached items with the enum item index. + /// Gets the flag values. /// - /// The type of enumeration - /// if set to true [humanize]. + /// The type of the enum. + /// The value. + /// if set to true [ignore zero]. /// - /// A collection of Type/Tuple pairs that represents items with the enum item value + /// A list of values in the flag /// - public static Tuple[] GetItemsWithIndex(bool humanize = true) + public static List GetFlagValues(int value, bool ignoreZero = false) + where TEnum : struct, IConvertible { - lock (LockObject) - { - var tupleName = typeof(T); - - if (IndexCache.ContainsKey(tupleName) == false) - { - var i = 0; - - IndexCache.Add(tupleName, Enum.GetNames(tupleName) - .Select(x => new Tuple(i++, humanize ? x.Humanize() : x)) - .ToArray()); - } - - return IndexCache[tupleName]; - } + return Retrieve() + .Select(x => (int) x.Item2) + .When(() => ignoreZero, q => q.Where(f => f != 0)) + .Where(x => (x & value) == x) + .ToList(); } /// - /// Gets the cached values array. + /// Gets the flag values. /// /// The type of the enum. - /// The array with values from the enumeration - public static Array GetValuesArray() + /// The value. + /// if set to true [ignore zero]. + /// + /// A list of values in the flag + /// + public static List GetFlagValues(long value, bool ignoreZero = false) + where TEnum : struct, IConvertible { - lock (LockObject) - { - var key = typeof(TEnum); - - if (ArrayValueCache.ContainsKey(key) == false) - { - ArrayValueCache.Add(key, Enum.GetValues(typeof(TEnum))); - } - - return ArrayValueCache[key]; - } + return Retrieve() + .Select(x => (long) x.Item2) + .When(() => ignoreZero, q => q.Where(f => f != 0)) + .Where(x => (x & value) == x) + .ToList(); } /// @@ -103,44 +91,92 @@ public static Array GetValuesArray() /// /// A list of values in the flag /// - public static List GetFlagValues(int value, bool ignoreZero = false) + public static List GetFlagValues(byte value, bool ignoreZero = false) where TEnum : struct, IConvertible { - return GetValuesArray() - .Cast() + return Retrieve() + .Select(x => (byte) x.Item2) .When(() => ignoreZero, q => q.Where(f => f != 0)) - .Where(f => (f & value) == f) + .Where(x => (x & value) == x) .ToList(); } /// - /// Gets the flag values. + /// Gets the flag names + /// + /// The type of the enum + /// the value + /// if set to true [ignore zero]. + /// if set to true [humanize]. + /// + /// A list of flag names + /// + public static List GetFlagNames(int value, bool ignoreZero = false, bool humanize = true) + where TEnum : struct, IConvertible + { + return Retrieve() + .When(() => ignoreZero, q => q.Where(f => (int) f.Item2 != 0)) + .Where(x => ((int) x.Item2 & value) == (int) x.Item2) + .Select(x => humanize ? x.Item1.Humanize() : x.Item1) + .ToList(); + } + + /// + /// Gets the flag names. /// /// The type of the enum. /// The value. - /// A list of values in the flag - public static List GetFlagValues(long value) + /// if set to true [ignore zero]. + /// if set to true [humanize]. + /// + /// A list of flag names + /// + public static List GetFlagNames(long value, bool ignoreZero = false, bool humanize = true) where TEnum : struct, IConvertible { - return GetValuesArray() - .Cast() - .Where(f => (f & value) == f) + return Retrieve() + .When(() => ignoreZero, q => q.Where(f => (long) f.Item2 != 0)) + .Where(x => ((long) x.Item2 & value) == (long) x.Item2) + .Select(x => humanize ? x.Item1.Humanize() : x.Item1) .ToList(); } /// - /// Gets the flag values. + /// Gets the flag names. /// /// The type of the enum. /// The value. - /// A list of values in the flag - public static List GetFlagValues(byte value) + /// if set to true [ignore zero]. + /// if set to true [humanize]. + /// + /// A list of flag names + /// + public static List GetFlagNames(byte value, bool ignoreZero = false, bool humanize = true) where TEnum : struct, IConvertible { - return GetValuesArray() - .Cast() - .Where(f => (f & value) == f) + return Retrieve() + .When(() => ignoreZero, q => q.Where(f => (byte) f.Item2 != 0)) + .Where(x => ((byte) x.Item2 & value) == (byte) x.Item2) + .Select(x => humanize ? x.Item1.Humanize() : x.Item1) .ToList(); } + + /// + /// Gets the cached items with the enum item index. + /// + /// The type of enumeration + /// if set to true [humanize]. + /// + /// A collection of Type/Tuple pairs that represents items with the enum item value + /// + public static Tuple[] GetItemsWithIndex(bool humanize = true) + where T : struct, IConvertible + { + var i = 0; + + return Retrieve() + .Select(x => new Tuple(i++, humanize ? x.Item1.Humanize() : x.Item1)) + .ToArray(); + } } } \ No newline at end of file diff --git a/src/Unosquare.Swan.Lite/Runtime.cs b/src/Unosquare.Swan.Lite/Runtime.cs index 471a4b1f3..745fbcca0 100644 --- a/src/Unosquare.Swan.Lite/Runtime.cs +++ b/src/Unosquare.Swan.Lite/Runtime.cs @@ -21,7 +21,9 @@ public static class Runtime private static readonly Lazy _propertyTypeCache = new Lazy(() => new PropertyTypeCache()); private static readonly Lazy _attributeCache = new Lazy(() => new AttributeCache()); - + + private static readonly Lazy _enumHelper = new Lazy(() => new EnumHelper()); + private static readonly Lazy _objectValidator = new Lazy(() => new ObjectValidator()); private static readonly Lazy _fieldTypeCache = new Lazy(() => new FieldTypeCache()); @@ -181,7 +183,7 @@ public static bool IsTheOnlyInstance /// The attribute cache. /// public static AttributeCache AttributeCache => _attributeCache.Value; - + /// /// Gets the object validator. /// diff --git a/src/Unosquare.Swan.Lite/Unosquare.Swan.Lite.csproj b/src/Unosquare.Swan.Lite/Unosquare.Swan.Lite.csproj index 185430bd1..428286536 100644 --- a/src/Unosquare.Swan.Lite/Unosquare.Swan.Lite.csproj +++ b/src/Unosquare.Swan.Lite/Unosquare.Swan.Lite.csproj @@ -10,7 +10,7 @@ Unosquare.Swan.Lite ..\..\StyleCop.Analyzers.ruleset Full - 0.27.0 + 0.28.0 Unosquare https://github.com/unosquare/swan/raw/master/swan-logo-32.png https://github.com/unosquare/swan diff --git a/src/Unosquare.Swan/Unosquare.Swan.csproj b/src/Unosquare.Swan/Unosquare.Swan.csproj index af503e3f9..b8419ac37 100644 --- a/src/Unosquare.Swan/Unosquare.Swan.csproj +++ b/src/Unosquare.Swan/Unosquare.Swan.csproj @@ -10,7 +10,7 @@ Unosquare.Swan ..\..\StyleCop.Analyzers.ruleset Full - 0.27.0 + 0.28.0 Unosquare https://github.com/unosquare/swan/raw/master/swan-logo-32.png https://github.com/unosquare/swan diff --git a/test/Unosquare.Swan.Test/EnumHelperTest.cs b/test/Unosquare.Swan.Test/EnumHelperTest.cs index e9bf6cbf0..7e6e90cae 100644 --- a/test/Unosquare.Swan.Test/EnumHelperTest.cs +++ b/test/Unosquare.Swan.Test/EnumHelperTest.cs @@ -17,12 +17,6 @@ public void WithValidIndexEnum_ReturnsTuple() Assert.AreEqual("(1, Two)", items[1].ToString()); Assert.AreEqual("(2, Three)", items[2].ToString()); } - - [Test] - public void WithInvalidType_ThrowsArgumentException() - { - Assert.Throws(() => EnumHelper.GetItemsWithIndex()); - } } [TestFixture] @@ -37,18 +31,12 @@ public void WithValidValueEnum_ReturnsTuple() Assert.AreEqual("(2, Two)", items[1].ToString()); Assert.AreEqual("(3, Three)", items[2].ToString()); } - - [Test] - public void WithInvalidType_ThrowsArgumentException() - { - Assert.Throws(() => EnumHelper.GetItemsWithValue()); - } } [TestFixture] public class GetFlagValues { - [TestCase(MyFlag.None, false, new[] {0})] + [TestCase(MyFlag.NoneOrZero, false, new[] {0})] [TestCase(MyFlag.One, false, new[] {0, 1})] [TestCase(MyFlag.Two, false, new[] {0, 2})] [TestCase(MyFlag.All, false, new[] {0, 1, 2, 3})] @@ -80,4 +68,25 @@ public void WithInvalidType_ThrowsArgumentException() Assert.Throws(() => EnumHelper.GetFlagValues(0)); } } + + [TestFixture] + public class GetFlagNames + { + [TestCase(false, false, "NoneOrZero", "One")] + [TestCase(false, true, "None Or Zero", "One")] + [TestCase(true, false, "One", "Two")] + public void WithFlag_ReturnsListofStrings(bool ignoreZero, bool humanize, string zeroIndexValue, string oneIndexValue) + { + var names = EnumHelper.GetFlagNames((int)MyFlag.All, ignoreZero, humanize); + + Assert.AreEqual(zeroIndexValue, names[0]); + Assert.AreEqual(oneIndexValue, names[1]); + } + + [Test] + public void WithInvalidType_ThrowsArgumentException() + { + Assert.Throws(() => EnumHelper.GetFlagNames(0)); + } + } } \ No newline at end of file diff --git a/test/Unosquare.Swan.Test/Mocks/JsonMock.cs b/test/Unosquare.Swan.Test/Mocks/JsonMock.cs index 5732f420b..86a554d14 100644 --- a/test/Unosquare.Swan.Test/Mocks/JsonMock.cs +++ b/test/Unosquare.Swan.Test/Mocks/JsonMock.cs @@ -138,7 +138,7 @@ public enum MyEnum [Flags] public enum MyFlag { - None = 0, + NoneOrZero = 0, One = 1, Two = 2, All = One | Two,