diff --git a/README.md b/README.md index 08833da..cfdfc63 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ - [Object Extensions](#object-extensions) - [DataTable Extensions](#datatable-extensions) - [Guid Extensions](#guid-extensions) + - [Enum Extensions](#enum-extensions) - [Logging](#logging) - [File Logger](#file-logger) - [JSON File Logger](#json-file-logger) @@ -1039,6 +1040,47 @@ Processes.TryStart("notepad.exe", "", 0, false, out var error); --- +## Enum Extensions + +The `EnumExtensions` class provides utility methods for working with enum types, specifically for retrieving display names defined via the `DisplayAttribute`. + +--- + +#### Features + +1. **Get Display Name**: + - Retrieve the value of the `DisplayAttribute.Name` property for an enum value, or fall back to the enum's name if the attribute is not present. + +--- + +#### Example Usage + +```csharp +using System.ComponentModel.DataAnnotations; +using MaksIT.Core.Extensions; + +public enum Status { + [Display(Name = "In Progress")] + InProgress, + Completed +} + +var status = Status.InProgress; +string displayName = status.GetDisplayName(); // "In Progress" + +var completed = Status.Completed; +string completedName = completed.GetDisplayName(); // "Completed" +``` + +--- + +#### Best Practices + +- Use the `Display` attribute on enum members to provide user-friendly names for UI or logging. +- Use `GetDisplayName()` to consistently retrieve display names for enums throughout your application. + +--- + ## Contact For any inquiries or contributions, feel free to reach out: diff --git a/src/MaksIT.Core.Tests/Extensions/EnumExtensionsTests.cs b/src/MaksIT.Core.Tests/Extensions/EnumExtensionsTests.cs new file mode 100644 index 0000000..0ad5f73 --- /dev/null +++ b/src/MaksIT.Core.Tests/Extensions/EnumExtensionsTests.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations; +using MaksIT.Core.Extensions; +using Xunit; + +namespace MaksIT.Core.Tests.Extensions; + +public class EnumExtensionsTests +{ + private enum TestEnum + { + [Display(Name = "First Value")] + First, + Second + } + + [Fact] + public void GetDisplayName_ReturnsDisplayName_WhenDisplayAttributeIsPresent() + { + // Arrange + var value = TestEnum.First; + + // Act + var displayName = value.GetDisplayName(); + + // Assert + Assert.Equal("First Value", displayName); + } + + [Fact] + public void GetDisplayName_ReturnsEnumName_WhenDisplayAttributeIsAbsent() + { + // Arrange + var value = TestEnum.Second; + + // Act + var displayName = value.GetDisplayName(); + + // Assert + Assert.Equal("Second", displayName); + } +} diff --git a/src/MaksIT.Core/Extensions/EnumExtensions.cs b/src/MaksIT.Core/Extensions/EnumExtensions.cs new file mode 100644 index 0000000..4fbc838 --- /dev/null +++ b/src/MaksIT.Core/Extensions/EnumExtensions.cs @@ -0,0 +1,14 @@ +using System.Reflection; +using System.ComponentModel.DataAnnotations; + + +namespace MaksIT.Core.Extensions; + +public static class EnumExtensions { + public static string GetDisplayName(this TEnum value) where TEnum : Enum { + var type = typeof(TEnum); + var memInfo = type.GetMember(value.ToString()); + var attributes = memInfo[0].GetCustomAttribute(); + return attributes?.Name ?? value.ToString(); + } +} diff --git a/src/MaksIT.Core/Extensions/StringExtensions.cs b/src/MaksIT.Core/Extensions/StringExtensions.cs index 1c044d1..73dc083 100644 --- a/src/MaksIT.Core/Extensions/StringExtensions.cs +++ b/src/MaksIT.Core/Extensions/StringExtensions.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Data; using System.Globalization; -using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.Json; @@ -219,17 +216,35 @@ namespace MaksIT.Core.Extensions { return plainText; } - public static string ToCamelCase(this string input) { + public static string ToCase(this string input, StringCaseStyle style) { if (string.IsNullOrEmpty(input)) return input; - var words = input.Split(new[] { ' ', '-', '_' }, StringSplitOptions.RemoveEmptyEntries); - for (var i = 0; i < words.Length; i++) { - words[i] = i == 0 ? words[i].ToLower() : char.ToUpper(words[i][0]) + words[i][1..].ToLower(); - } + var words = Regex.Split(input, @"[^a-zA-Z0-9]+") + .Where(w => !string.IsNullOrEmpty(w)) + .ToArray(); - return string.Join("", words); + if (words.Length == 0) return string.Empty; + + switch (style) { + case StringCaseStyle.CamelCase: + return words[0].ToLowerInvariant() + + string.Concat(words.Skip(1).Select(w => char.ToUpperInvariant(w[0]) + w[1..].ToLowerInvariant())); + case StringCaseStyle.PascalCase: + return string.Concat(words.Select(w => char.ToUpperInvariant(w[0]) + w[1..].ToLowerInvariant())); + case StringCaseStyle.SnakeCase: + return string.Join("_", words.Select(w => w.ToLowerInvariant())); + case StringCaseStyle.KebabCase: + return string.Join("-", words.Select(w => w.ToLowerInvariant())); + default: + throw new ArgumentOutOfRangeException(nameof(style), style, null); + } } + public static string ToCamelCase(this string input) => input.ToCase(StringCaseStyle.CamelCase); + public static string ToPascalCase(this string input) => input.ToCase(StringCaseStyle.PascalCase); + public static string ToSnakeCase(this string input) => input.ToCase(StringCaseStyle.SnakeCase); + public static string ToKebabCase(this string input) => input.ToCase(StringCaseStyle.KebabCase); + public static DataTable CSVToDataTable(this string filePath) { if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException(nameof(filePath)); @@ -273,4 +288,12 @@ namespace MaksIT.Core.Extensions { return true; } } + + + public enum StringCaseStyle { + CamelCase, + PascalCase, + SnakeCase, + KebabCase + } } diff --git a/src/MaksIT.Core/MaksIT.Core.csproj b/src/MaksIT.Core/MaksIT.Core.csproj index 9b23556..5608ddf 100644 --- a/src/MaksIT.Core/MaksIT.Core.csproj +++ b/src/MaksIT.Core/MaksIT.Core.csproj @@ -8,7 +8,7 @@ MaksIT.Core - 1.5.1 + 1.5.2 Maksym Sadovnychyy MAKS-IT MaksIT.Core