BrainEnterprise.Core.Enums
13.0.0
Prefix Reserved
dotnet add package BrainEnterprise.Core.Enums --version 13.0.0
NuGet\Install-Package BrainEnterprise.Core.Enums -Version 13.0.0
<PackageReference Include="BrainEnterprise.Core.Enums" Version="13.0.0" />
<PackageVersion Include="BrainEnterprise.Core.Enums" Version="13.0.0" />
<PackageReference Include="BrainEnterprise.Core.Enums" />
paket add BrainEnterprise.Core.Enums --version 13.0.0
#r "nuget: BrainEnterprise.Core.Enums, 13.0.0"
#:package BrainEnterprise.Core.Enums@13.0.0
#addin nuget:?package=BrainEnterprise.Core.Enums&version=13.0.0
#tool nuget:?package=BrainEnterprise.Core.Enums&version=13.0.0
BrainEnterprise.Core.Enums
Libreria di utilità per la gestione degli Enum in .NET. Fornisce helper per descrizioni leggibili e testi estesi, conversione in DataTable/List, metadata UI, colori di stato, raggruppamento, extension methods e gestione completa delle transizioni di stato.
Versione corrente: 13.0.0. Le rotture rispetto alle major precedenti sono in fondo, nella sezione Breaking changes.
Target Framework
- .NET Standard 2.0
- .NET Framework 4.6.2
- .NET 9
Installazione
dotnet add package BrainEnterprise.Core.Enums
Classi principali
| Classe | Namespace | Descrizione |
|---|---|---|
EnumHelper |
BrainEnterprise.Core.Enums |
Metodi statici per convertire enum in DataTable, List<EnumItem> e proiezione per il binding |
EnumItem |
BrainEnterprise.Core.Enums |
DTO con proprietà Id e SortOrder (int), Description, Hint e Group (string) |
HintAttribute |
BrainEnterprise.Core.Enums.Attributes |
Attributo per il testo esteso di un valore (tooltip, help contestuale) |
StatusColorAttribute |
BrainEnterprise.Core.Enums.Attributes |
Attributo per i colori di stato: tema chiaro, tema scuro, sfondo e testo del badge |
EnumMetadataAttribute |
BrainEnterprise.Core.Enums.Attributes |
Attributo per metadata UI: Icon, CssClass, SortOrder, IsActive |
EnumGroupAttribute |
BrainEnterprise.Core.Enums.Attributes |
Attributo per raggruppare valori enum sotto un nome logico |
EnumExtensions |
BrainEnterprise.Core.Enums.Extensions |
Extension methods sui metadata: ToDescription(), ToColor() (deprecata), ToIcon(), ToCssClass(), ToSortOrder(), ToIsActive(), ToGroup(), EnumMetadataInfo() |
EnumMeta |
BrainEnterprise.Core.Enums.Extensions |
Punto di accesso unico ai testi di un valore: GetTexts(), GetDescription(), GetHint() |
EnumMeta.Texts |
BrainEnterprise.Core.Enums.Extensions |
Coppia immutabile Description + Hint restituita da GetTexts() |
StatusColorExtensions |
BrainEnterprise.Core.Enums.Extensions |
Extension methods sui colori di stato: StatusColorInfo(), StatusColor(), StatusDarkColor(), StatusBadgeBackground(), StatusBadgeForeground() |
AllowedTransitionsAttribute |
BrainEnterprise.Core.Enums.Transitions |
Attributo per dichiarare gli stati successivi consentiti |
StatusTransitionHelper |
BrainEnterprise.Core.Enums.Transitions |
Helper statico per transizioni basate su attributi |
TransitionRule<TEnum> |
BrainEnterprise.Core.Enums.Transitions |
Regola di transizione con condizione opzionale e descrizione |
StatusMachine<TEnum> |
BrainEnterprise.Core.Enums.Transitions |
State machine configurabile con API fluent: Allow(), CanTransition(), Transition(), GetAllowedNextStatuses() |
Utilizzo
Enum di esempio
using System.ComponentModel;
using BrainEnterprise.Core.Enums.Attributes;
using BrainEnterprise.Core.Enums.Transitions;
public enum OrderStatus
{
[Description("In attesa di pagamento")]
[Hint("L'ordine è registrato ma non ancora pagato: non viene preso in carico dal magazzino.")]
[StatusColor("#FFA500", DarkColor = "#FBBF24", BadgeBackground = "#FEF3C7")]
[EnumMetadata(Icon = "hourglass", CssClass = "badge-warning", SortOrder = 10)]
[EnumGroup("Attivi")]
[AllowedTransitions((int)Confirmed, (int)Cancelled)]
Pending = 0,
[Description("Confermato")]
[StatusColor("#007BFF")]
[EnumMetadata(Icon = "check", CssClass = "badge-info", SortOrder = 20)]
[EnumGroup("Attivi")]
[AllowedTransitions((int)Shipped, (int)Cancelled)]
Confirmed = 1,
[Description("Spedito")]
[StatusColor("#17A2B8")]
[EnumMetadata(Icon = "truck", CssClass = "badge-primary")]
[EnumGroup("Attivi")]
[AllowedTransitions((int)Delivered)]
Shipped = 2,
[Description("Consegnato")]
[StatusColor("#28A745")]
[EnumMetadata(Icon = "package", CssClass = "badge-success")]
[EnumGroup("Chiusi")]
Delivered = 3,
[Description("Annullato")]
[StatusColor("#DC3545")]
[EnumMetadata(Icon = "x-circle", CssClass = "badge-danger", IsActive = false)]
[EnumGroup("Chiusi")]
Cancelled = 4
}
ToDataTable / ToList / ToItems
using BrainEnterprise.Core.Enums;
DataTable table = EnumHelper.ToDataTable<OrderStatus>();
// Id | Description
// 0 | In attesa di pagamento
// 1 | Confermato
// ...
DataTable full = EnumHelper.ToDataTable<OrderStatus>(includeHint: true, includeGroup: true);
// Id | Description | Hint | Group
// 0 | In attesa di pagamento | L'ordine è registrato ma ... | Attivi
// 1 | Confermato | (vuoto: membro non decorato) | Attivi
// i due flag sono indipendenti: con il solo includeGroup la colonna Group è la terza
List<EnumItem> items = EnumHelper.ToList<OrderStatus>();
// [{ Id = 0, Description = "In attesa di pagamento", Hint = "L'ordine è ...", Group = "Attivi" }, ...]
IList<EnumItem> forBinding = EnumHelper.ToItems<OrderStatus>();
// come ToList, ma ordinato per valore numerico: è la sorgente pensata per il binding
// (DevExpress ImageComboBoxEdit / LookUpEdit, dropdown ASPx), con il tooltip di riga
// agganciato a Hint senza reflection nel layer di presentazione
IList<EnumItem> byPosition = EnumHelper.ToItems<OrderStatus>(orderBySortOrder: true);
DataTable sorted = EnumHelper.ToDataTable<OrderStatus>(orderBySortOrder: true);
// ordinati per EnumMetadata.SortOrder invece che per valore numerico
Le colonne Hint e Group di ToDataTable sono opt-in: per default la tabella mantiene le
sole colonne Id e Description, così le griglie che generano le colonne automaticamente non
ne vedono di nuove. L'ordine è sempre Id, Description, Hint, Group, e i membri privi
di testo esteso o di gruppo valgono stringa vuota, non DBNull: la tabella si aggancia ad
un binding senza dover gestire il null, come già fanno le estensioni sui colori di stato.
Su EnumItem le stesse proprietà restano invece a null, coerentemente con GetHint() e
ToGroup().
La DataTable prende il nome del tipo enumerativo (TableName = "OrderStatus").
L'ordine di presentazione si controlla con EnumMetadataAttribute.SortOrder e il flag
orderBySortOrder, disponibile sia su ToDataTable sia su ToItems. Anche questo è opt-in:
per default ToItems ordina per valore numerico e ToDataTable segue l'ordine di
dichiarazione, come prima. Con il flag attivo l'ordinamento è SortOrder e, a parità, il
valore numerico: i membri privi di EnumMetadata valgono SortOrder 0, quindi precedono
quelli con un ordinamento positivo, restando fra loro in ordine numerico. Se l'enumerativo
mescola membri decorati e non, conviene decorarli tutti.
Il parametro generico è vincolato a struct, Enum: passare un tipo che non è un enumerativo è
un errore di compilazione. Il valore numerico è esposto come int, quindi un enumerativo con
underlying type long o ulong fuori dal range di int fa lanciare OverflowException.
Extension methods
using BrainEnterprise.Core.Enums.Attributes;
using BrainEnterprise.Core.Enums.Extensions;
OrderStatus status = OrderStatus.Pending;
string desc = status.ToDescription(); // "In attesa di pagamento"
string icon = status.ToIcon(); // "hourglass"
string css = status.ToCssClass(); // "badge-warning"
int order = status.ToSortOrder(); // 10 (0 se non specificato)
bool active = status.ToIsActive(); // true (un valore non decorato è considerato attivo)
string group = status.ToGroup(); // "Attivi"
// quando servono più metadati sullo stesso valore, una sola lettura
EnumMetadataAttribute metadata = status.EnumMetadataInfo(); // null se non decorato
Per i colori si usa StatusColor() (vedi sotto). ToColor() ed EnumMetadataAttribute.Color
restano disponibili ma sono [Obsolete] dalla 13.0.0.
Testo esteso con HintAttribute
DescriptionAttribute resta l'etichetta breve mostrata in elenchi e combo; HintAttribute
affianca un testo più esteso da usare come tooltip o help contestuale. I due canali sono
indipendenti: aggiungere un hint non tocca ciò che già legge la descrizione.
using BrainEnterprise.Core.Enums.Extensions;
OrderStatus status = OrderStatus.Pending;
string label = status.GetDescription(); // "In attesa di pagamento"
string tooltip = status.GetHint(); // "L'ordine è registrato ma ..." (null se non decorato)
// unica lettura quando servono entrambi
EnumMeta.Texts texts = status.GetTexts();
Un valore non definito nell'enumerativo — tipicamente un intero letto da database — non lancia
eccezioni: degrada su ToString() con Hint a null.
Colori di stato con StatusColorAttribute
StatusColorAttribute tiene insieme le varianti di colore di un valore — tema chiaro, tema
scuro, sfondo e testo del badge — e le fa ricadere l'una sull'altra. I colori sono stringhe
esadecimali, così l'assembly non è vincolato ad una specifica tecnologia di presentazione.
using BrainEnterprise.Core.Enums.Attributes;
using BrainEnterprise.Core.Enums.Extensions;
OrderStatus status = OrderStatus.Pending;
string light = status.StatusColor(); // "#FFA500"
string dark = status.StatusDarkColor(); // "#FBBF24"
string badgeBack = status.StatusBadgeBackground(); // "#FEF3C7"
string badgeFore = status.StatusBadgeForeground(); // non specificato: ricade su Color
// l'attributo completo, o null se il valore non è decorato
StatusColorAttribute info = status.StatusColorInfo();
I metodi restituiscono stringa vuota — non null — quando il valore non è decorato, per poter essere usati direttamente in un binding.
Transizioni di stato con attributi
StatusTransitionHelper utilizza AllowedTransitionsAttribute per validare le transizioni.
L'assenza dell'attributo su un valore significa "stato finale".
using BrainEnterprise.Core.Enums.Transitions;
// Verifica se una transizione è consentita
bool ok = StatusTransitionHelper.CanTransition(OrderStatus.Pending, OrderStatus.Confirmed); // true
bool ko = StatusTransitionHelper.CanTransition(OrderStatus.Pending, OrderStatus.Delivered); // false
// Esegue la transizione o lancia InvalidOperationException
var next = StatusTransitionHelper.Transition(OrderStatus.Pending, OrderStatus.Confirmed);
// Ottiene gli stati raggiungibili
var allowed = StatusTransitionHelper.GetAllowedNextStatuses(OrderStatus.Pending);
// EnumItem completi: Id, Description e, se i membri sono decorati, anche Hint e Group
// [{ Id = 1, Description = "Confermato", Group = "Attivi" }, { Id = 4, ... }]
State machine configurabile
StatusMachine<TEnum> permette di definire transizioni a runtime con API fluent, supportando condizioni opzionali.
using BrainEnterprise.Core.Enums.Transitions;
var machine = new StatusMachine<OrderStatus>()
.Allow(OrderStatus.Pending, OrderStatus.Confirmed, "Conferma ordine")
.Allow(OrderStatus.Pending, OrderStatus.Cancelled, "Annullamento")
.Allow(OrderStatus.Confirmed, OrderStatus.Shipped, "Spedizione")
.Allow(OrderStatus.Confirmed, OrderStatus.Cancelled, "Annullamento post-conferma")
.Allow(OrderStatus.Shipped, OrderStatus.Delivered, "Consegna avvenuta");
// Verifica transizione
bool canShip = machine.CanTransition(OrderStatus.Confirmed, OrderStatus.Shipped); // true
// Esegue la transizione o lancia InvalidOperationException
var next = machine.Transition(OrderStatus.Confirmed, OrderStatus.Shipped);
// Stati raggiungibili
var nextStates = machine.GetAllowedNextStatuses(OrderStatus.Confirmed);
// [{ Id = 2, Description = "Spedito", Group = "Attivi" }, { Id = 4, ... }]
// Transizione condizionale
bool isPaid = true;
var conditionalMachine = new StatusMachine<OrderStatus>()
.Allow(OrderStatus.Pending, OrderStatus.Confirmed,
"Conferma solo se pagato",
condition: () => isPaid);
L'istanza non è thread-safe in scrittura: va configurata una sola volta, prima di essere condivisa fra più thread in lettura.
TransitionRule<TEnum> è la forma della singola regola: From, To, Description e la
Condition opzionale. Serve quando le regole non si dichiarano una ad una ma arrivano da una
sorgente esterna — tipicamente la configurazione — e si passano già pronte all'overload
Allow(TransitionRule<TEnum>):
var rule = new TransitionRule<OrderStatus>
{
From = OrderStatus.Pending,
To = OrderStatus.Confirmed,
Description = "Conferma ordine",
Condition = () => isPaid // opzionale
};
var machine = new StatusMachine<OrderStatus>().Allow(rule);
La regola viene copiata: modificarla dopo la chiamata non altera il comportamento della
macchina a stati. Una regola null viene rifiutata con ArgumentNullException.
Cache e prestazioni
Tutte le letture di attributi passano da un'unica cache interna, indicizzata per coppia
valore/tipo di attributo: la reflection viene eseguita una sola volta per valore e l'accesso
è thread-safe (ConcurrentDictionary). Vale per ToDescription(), GetTexts(), i metadata di
presentazione, il gruppo e i colori di stato, cioè proprio le chiamate che si ripetono ad ogni
riga di una griglia.
Conseguenza da tenere presente: gli attributi restituiti da EnumMetadataInfo() e
StatusColorInfo() sono istanze condivise. Vanno considerati di sola lettura — modificarne
le proprietà altera il valore visto da tutti i chiamanti.
Breaking changes
13.0.0
Major di riordino: le rotture sono raccolte qui per non spezzare i consumer più volte.
- Vincolo generico
where TEnum : struct, EnumsuEnumHelper,StatusTransitionHelper,StatusMachine<TEnum>eTransitionRule<TEnum>. Passare una struct che non è un enumerativo è ora un errore di compilazione (CS0315) invece diArgumentExceptiona runtime. Di conseguenza quei metodi non lanciano piùArgumentException: itry/catchche la intercettavano sono codice morto. EnumItemè un tipo di primo livello, non più annidato inEnumHelper. I riferimenti scritti comeEnumHelper.EnumItemvanno aggiornati inEnumItem; chi usausing static BrainEnterprise.Core.Enums.EnumHelper;non è impattato.EnumMetadataAttributeedEnumGroupAttributesono passati al namespaceBrainEnterprise.Core.Enums.Attributes, insieme agli altri attributi: serve aggiungere lausing.AllowedTransitionsAttribute.AllowedNextStatusesèIReadOnlyList<int>invece diint[]. Chi lo assegnava ad unint[]deve usareToArray().StatusMachine.GetAllowedNextStatesè stato rinominato inGetAllowedNextStatuses, per allinearsi aStatusTransitionHelper. Il nome storico resta come[Obsolete]e delega al nuovo: verrà rimosso in una versione successiva.EnumMetadataAttribute.ColoredEnumExtensions.ToColor()sono[Obsolete]: i colori hanno un solo canale,StatusColorAttribute/StatusColor(). Compilano ancora, con warning CS0618.EnumItemha due proprietà in più,GroupeSortOrder, valorizzate daToList(),ToItems()e dagli helper di transizione. Come perHintnella 12.0.0, chi proiettaEnumItemsu una griglia con generazione automatica delle colonne vede due colonne in più. InToDataTable()la colonnaGroupresta opt-in eSortOrdernon viene esposta: serve solo ad ordinare, tramite il flagorderBySortOrder.
12.0.0
Nessuna firma pubblica rimossa o modificata: chi aggiornava da 11.0.0 non doveva toccare il codice. Cambiavano però alcuni comportamenti.
- Gli attributi restituiti sono istanze condivise.
EnumMetadataInfo()eStatusColorInfo()restituiscono l'istanza in cache invece di una nuova ad ogni chiamata. Codice che ne modificava le proprietà dopo la lettura influenza tutti i chiamanti. ToDescription()su un valore null non lancia piùNullReferenceException: restituisce stringa vuota.EnumItemha una proprietà in più (Hint), valorizzata anche daToList(),GetAllowedNextStatuses(). Chi proiettaEnumItemsu una griglia con generazione automatica delle colonne vede una colonna in più.ToDataTable()non è cambiato: espone sempre e soloIdeDescription. Dalla 13.0.0 le colonne opzionali si richiedono esplicitamente conToDataTable<TEnum>(includeHint: true, includeGroup: true).- I pacchetti Debug non contengono più i simboli (
DebugType=none), allineandosi alle altre librerie del workspace. I simboli restano nei pacchetti Release.
In entrambi i major cambia l'AssemblyVersion, quindi i consumer su .NET Framework devono
aggiornare gli eventuali binding redirect.
Licenza
MIT - 2026 Brain Enterprise S.r.l.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.6.2
- No dependencies.
-
.NETStandard 2.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.