Cayaqui.MPS.Metadata
0.17.1
dotnet add package Cayaqui.MPS.Metadata --version 0.17.1
NuGet\Install-Package Cayaqui.MPS.Metadata -Version 0.17.1
<PackageReference Include="Cayaqui.MPS.Metadata" Version="0.17.1" />
<PackageVersion Include="Cayaqui.MPS.Metadata" Version="0.17.1" />
<PackageReference Include="Cayaqui.MPS.Metadata" />
paket add Cayaqui.MPS.Metadata --version 0.17.1
#r "nuget: Cayaqui.MPS.Metadata, 0.17.1"
#:package Cayaqui.MPS.Metadata@0.17.1
#addin nuget:?package=Cayaqui.MPS.Metadata&version=0.17.1
#tool nuget:?package=Cayaqui.MPS.Metadata&version=0.17.1
Cayaqui.MPS.Metadata
Zero-dependency attributes + resolver para decorar DTOs con metadata consumida por web grids, Cayaqui.MPS.Reports y Cayaqui.MPS.ExcelImport. Un solo decorado → tres usos consistentes.
Distribución propietaria — requiere contrato comercial con Cayaqui. Ver
LICENSE.txt.
v0.4.0 — Enum [Display(Name)] resolution + idempotencia
IExtendedPropertyResolver.Format() ahora resuelve [Display(Name="…")] para valores enum (antes devolvía el identifier C# directo). Esto hace que los componentes de Cayaqui.MPS.Components (MpsAutoGrid, MpsAutoBadge, MpsAutoForm read-only) y los renderers de Cayaqui.MPS.Reports muestren labels localizados.
public enum Status
{
[Display(Name = "Aprobado")] Approved,
[Display(Name = "Rechazado")] Rejected,
}
resolver.Format(Status.Approved, typeof(Row), nameof(Row.Status));
// → "Aprobado" (era "Approved" en 0.3.x)
Cambio aditivo: enums sin [Display] siguen devolviendo value.ToString(). Limitación: enums [Flags] con combinación bit-OR caen al ToString() de .NET ("A, B, C" con identifiers C#) — resolución bit-a-bit es follow-up.
Bug fix idempotencia DI: AddMpsMetadata() y los demás AddMpsX() usan ahora TryAddSingleton/TryAddScoped. Múltiples llamadas (que ocurren cuando otros helpers como AddMpsComponents() lo invocan internamente) no duplican los registros.
Nuevo helper público: EnumExtensions.GetDisplayName() para uso fuera del resolver (charts, chips, código manual).
Instalación
dotnet add package Cayaqui.MPS.Metadata
builder.Services.AddMpsMetadata(); // registra IExtendedPropertyResolver singleton
Ejemplo
public sealed class ControlAccountDto
{
[Label("Código CA")] [Wbs] [UpperCase]
[NotEmpty] [MaxLength(20)] [RegularExpression(@"^[A-Z]{2,3}-\d{3,}$")]
[ImportAlias("Code", "Control Account")]
public string Code { get; set; } = "";
[Currency("USD", 2)] [Money] [Align(TextAlign.Right)] [ColumnWidth(140)]
public decimal Bac { get; set; }
[Percentage(1)] [EvmIndicator(EvmKind.Cpi)] [EvmBand(green: 0.97, yellow: 0.90)]
public decimal Cpi { get; set; }
[Date("dd-MMM-yy")] [Schedule]
public DateTime ControlDate { get; set; }
[Badge] // reads colors from BadgeEnum values
public ProjectStatus Status { get; set; }
[Mask(MaskKind.Email, visibleChars: 1)] [Tooltip("Owner email (masked)")]
public string Owner { get; set; } = "";
[Hidden]
public Guid InternalId { get; set; }
[ImportAlias("SPI", "Schedule Performance Index")]
[ImportCulture("es-CL")]
public decimal Spi { get; set; }
}
public enum ProjectStatus
{
[BadgeColor(BadgeKind.Neutral)] Draft,
[BadgeColor(BadgeKind.Info)] InReview,
[BadgeColor(BadgeKind.Success)] Approved,
[BadgeColor(BadgeKind.Warning)] OnHold,
[BadgeColor(BadgeKind.Error)] Cancelled
}
Los 37 atributos
Display
[Label("text")]— override (reuse[Display(Name)]si existe)[Tooltip("text")]— tooltip específico[Placeholder("text")]— placeholder input Blazor- Reusar
[Display(Name, Description, Order, GroupName)]de DataAnnotations
Format
[Currency("USD", 2)]—"USD 1,234.56"[Percentage(1)]—0.756→"75.6%"[Date("dd-MMM-yy")]— formato custom[Integer(thousands: true)]—"1,234,567"[DecimalFormat(decimals: 4)][Duration(DurationUnit.Days)]—"5d","3h","15m"
Transform (no mutan el valor, sólo el display)
[UpperCase]·[LowerCase]·[TitleCase][Mask(MaskKind.Email, visibleChars: 1)]→"a********@cayaqui.com"[Mask(MaskKind.Email, visibleChars: 3)]→"ale******@cayaqui.com"[Mask(MaskKind.LastChars, visibleChars: 4)]→"******7890"[Truncate(30)]
Layout / Visibility
[Align(TextAlign.Right)][ColumnWidth(150)][VisibleIn(RenderTargets.Web | RenderTargets.Report)][Hidden]— shortcut de[VisibleIn(None)][ReadOnlyDisplay]
Badge
[Badge(BadgeKind.Success)]— fijo[Badge]+[BadgeColor(...)]en cada valor del enum — mapeado por valor
Usuario / persona
[UserColumn]— marca una propstringcomo nombre de usuario para queMpsAutoGridla renderice como<UserChip>. Opcionales:AvatarSource = "SiblingProp"— prop hermana con la URL del avatar.RoleSource = "SiblingProp"— prop hermana con el rol/cargo.
public sealed record AuditRow(
string Action,
[property: UserColumn(AvatarSource = "PerformedByAvatar", RoleSource = "PerformedByRole")]
string PerformedByName,
string? PerformedByAvatar,
string? PerformedByRole);
Cayaqui.MPS.Components 0.24+ consume este atributo automáticamente.
Validation (custom shortcuts — reuse DataAnnotations para el resto)
[NotEmpty]—[Required(AllowEmptyStrings = false)][Min(0)]/[Max(100)]— sugar sobre[Range]- Reusar
[Required],[MaxLength],[MinLength],[Range],[RegularExpression],[EmailAddress],[Phone],[Url]
EPC dominio
[EvmIndicator(EvmKind.Cpi)]— renderer aplica íconos/colores contextuales[EvmBand(green: 0.95, yellow: 0.85)]— thresholds semaforo configurables[Wbs]·[Cbs]·[Schedule]·[Money]— markers semánticos
Import
[ImportAlias("CPI", "Cost Performance Index")]— multi-header match[ImportIgnore][ImportDefault(0)][ImportCulture("es-CL")]— parsing locale[ImportColumn(3)]— opt-in por posición[ImportTrim(false)]— default true[ImportRegex(@"^[A-Z]+-\d+$")]
API del resolver
public interface IExtendedPropertyResolver
{
PropertyMetadata? Get(Type dtoType, string propertyName);
IReadOnlyList<PropertyMetadata> GetAll(Type dtoType);
/// <summary>
/// Filtra GetAll() por <see cref="RenderTargets"/> visible (Web | Report |
/// Excel). Usado por MpsAutoGrid/MpsAutoForm para descartar props
/// con [VisibleIn] que excluya el target actual.
/// </summary>
IReadOnlyList<PropertyMetadata> GetVisibleProperties(Type dtoType, RenderTargets target);
string? Format(object? value, Type dtoType, string propertyName, CultureInfo? culture = null);
bool TryParse(string? text, Type dtoType, string propertyName, CultureInfo? culture, out object? value);
}
RenderTargets es un enum bandera (en MPS.Metadata/Models/Enums.cs):
[Flags]
public enum RenderTargets
{
None = 0,
Web = 1 << 0, // grids, forms, modals en Blazor
Report = 1 << 1, // PDF/Word/PPT vía MPS.Reports
Excel = 1 << 2, // export a XLSX vía MPS.ExcelExport
All = Web | Report | Excel,
}
Helper público adicional (v0.4.0+):
namespace MPS.Metadata;
public static class EnumExtensions
{
/// Devuelve [Display(Name)] del miembro del enum, fallback a ToString().
public static string GetDisplayName(this Enum value);
}
Cache por Type en primer acceso, thread-safe.
Requisitos
- .NET 10.0 o superior
- Zero dependencies externas (sólo
Microsoft.Extensions.DependencyInjection.Abstractionspara el extension method, que es BCL+)
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
NuGet packages (5)
Showing the top 5 NuGet packages that depend on Cayaqui.MPS.Metadata:
| Package | Downloads |
|---|---|
|
Cayaqui.MPS.Components
Design system and EVM/EPC reusable components (KPI strip, gauges CPI/SPI/PF, S-curves, Gantt, WBS tree grid, R9C, risk heatmap, change orders, purchase orders, engineering deliverables, lookahead grid) for .NET 10 Blazor WebApp (Interactive Server) on top of Syncfusion.Blazor. Proprietary — requires a commercial agreement with Cayaqui. |
|
|
Cayaqui.MPS.ExcelExport
Exports strongly-typed collections of DTOs to .xlsx using the attributes from Cayaqui.MPS.Metadata: Label for headers, Currency/Percentage/Date for cell formats, Align/ColumnWidth for layout, VisibleIn/Hidden for visibility, Order for column order, Badge for cell background color. Uses Syncfusion XlsIO. Proprietary — requires a commercial agreement with Cayaqui. |
|
|
Cayaqui.MPS.Reports
Template-based report generation for .NET 10 using Syncfusion File Formats (OpenXML compliant). Supports Excel (XlsIO), Word (DocIO), PowerPoint (Presentation) templates with MailMerge / template markers / placeholder replacement, native chart generation, and PDF conversion. Templates are loaded from Cayaqui.MPS.Storage. Proprietary — requires a commercial agreement with Cayaqui. |
|
|
Cayaqui.MPS.Storage
Generic storage service for .NET 10 with pluggable providers (Azure Blob Storage, Local File System). Includes streaming upload/download, SAS/file URL generation, container/key model and DI options pattern. Proprietary — requires a commercial agreement with Cayaqui. |
|
|
Cayaqui.MPS.ExcelImport
Reads .xlsx files and materializes strongly-typed DTOs using the attributes from Cayaqui.MPS.Metadata (ImportAlias, ImportColumn, ImportCulture, ImportDefault, ImportTrim, ImportRegex) plus resolver-based TryParse. Uses Syncfusion XlsIO for spreadsheet access. Proprietary — requires a commercial agreement with Cayaqui. |
GitHub repositories
This package is not used by any popular GitHub repositories.
v0.4.0 — IExtendedPropertyResolver.Format ahora resuelve [Display(Name="…")] para valores enum (antes devolvía el identifier C#). Componentes de MPS.Components (MpsAutoGrid, MpsAutoBadge, MpsAutoForm) y renderers de MPS.Reports ahora muestran labels localizados sin código adicional. Cambio aditivo, sin breaking. Limitación: enums [Flags] con combinación bit-OR caen al ToString() de .NET (resolución bit-a-bit es follow-up). Adicional: AddMpsMetadata + AddMpsComponents + 8 helpers más usan TryAdd* — fixea idempotencia DI. Nuevo: EnumExtensions.GetDisplayName() público para uso fuera del resolver.