Utilidades
Primitivas de concurrencia y limitación, conversiones de tipos y familias de extensiones que trae el paquete Dinaup para .NET.
El paquete Dinaup incluye un módulo de utilidades con primitivas de concurrencia y limitación, conversiones de tipos y métodos de extensión. Todo vive en el paquete principal: no hay nada que instalar aparte.
using Dinaup;Primitivas de concurrencia y limitación
Piezas pequeñas y probadas para los problemas típicos de ritmo, caché y ejecución en background. Úsalas antes de resolverlo a mano.
Debouncer
Retrasa una acción asíncrona y cancela las llamadas anteriores si llega otra dentro de la ventana. Para operaciones caras disparadas por eventos rápidos (teclas, scroll, redibujados).
var debouncer = new Debouncer(async () => await GuardarBorradorAsync(), 500);
// Cada pulsación reinicia el contador; solo se guarda 500 ms tras la última.
debouncer.Debounce();ExpirableValue / ExpirableValueAsync
Envuelve un valor con expiración (TTL). Al leerlo, si ha caducado, llama a la función de refresco. Hay versión síncrona y asíncrona, genéricas sobre T.
// Refresca desde una fábrica cada 60 s.
var token = new ExpirableValueAsync<string>(
async () => await PedirTokenAsync(),
expirationInSeconds: 60);
string actual = await token.GetValueAsync();
// Versión síncrona con valor inicial o con actualizador.
var config = new ExpirableValue<int>(() => LeerConfig(), expirationInSeconds: 30);
int n = config.GetValue();RateLimiter
Limita intentos por clave. TryAttempt incrementa el contador de esa clave y devuelve false si supera el máximo. Se reinicia sola al vencer el intervalo.
var limiter = new RateLimiter(maxAttempts: 5, clearInterval: TimeSpan.FromMinutes(1));
if (limiter.TryAttempt(userEmail) == false)
throw new Exception("Demasiados intentos, prueba en un minuto.");TokenBucket
Cubo de tokens clásico. Se rellena a refillPerSecond tokens por segundo. TryConsume devuelve true si hay tokens y false si no.
var bucket = new TokenBucket(maxTokens: 100, refillPerSecond: 10);
if (bucket.TryConsume())
await LlamarApiExternaAsync();SlidingCounter
Limitador por ventana deslizante. TryAdd devuelve true mientras el número de eventos dentro de la ventana no supere el máximo; poda los eventos antiguos sola.
var counter = new SlidingCounter(maxEvents: 1000, window: TimeSpan.FromSeconds(10));
if (counter.TryAdd() == false)
return; // pico de actividad: descarta o encolaSerialQueue
Cola FIFO segura entre hilos para ejecutar tareas de una en una. Cada Enqueue devuelve un Task que completa cuando el trabajo termina. Evita ejecuciones concurrentes sin bloquear.
var queue = new SerialQueue();
// Se ejecutan en orden, nunca a la vez.
await queue.Enqueue(async () => await EscribirEnArchivoAsync(a));
var total = await queue.Enqueue(() => Calcular());IBackgroundTaskQueue
Cola de trabajo asíncrono con descripción por tarea. Enqueue añade trabajo; DequeueAsync bloquea hasta que hay una tarea. QueuedHostedService (un BackgroundService) las consume y ejecuta.
IBackgroundTaskQueue queue = new BackgroundTaskQueue();
queue.Enqueue(async ct => await ProcesarPedidoAsync(pedidoId, ct), "procesar-pedido");
int pendientes = queue.Count();
var resumen = queue.ResumenCola(); // descripción -> cuántas pendientesConversiones de tipos
Métodos de extensión para convertir entre tipos sin TryParse a mano ni excepciones inesperadas. Convierten desde String, Object, valores anulables y otros.
| Familia | Convierte a | Ejemplos de uso |
|---|---|---|
STR | String | precio.STR(), id.STR(), fecha.STR() — formatea decimales y fechas de forma coherente, tolera nulos. |
INT | Integer | texto.INT(0) (con defecto), texto.INT(min, max, siFalla) (con límites). |
ToDate y familia | Date / DateOnly / TimeOnly | s.ToDate(), s.ToDateOnly(), s.ToDateDesdeMySQL_utc(), variantes _Nullable y de zona horaria. |
ToSQL y familia | Literal SQL | nombre.ToSQL(), fecha.ToSQL_Date(), importe.ToSQL_Decimal() — para concatenar en sentencias. |
ToSHA1 | Hash hex | ToSHA1(bytes), ToSHA1(texto), ToSHA1(stream). |
int cantidad = Request["cantidad"].INT(0); // 0 si no es número
string fecha = DateTime.UtcNow.ToSQL_Date(); // literal para SQL
string hash = Dinaup.extensions.ToSHA1(bytes); // SHA-1 en hexToSQL produce literales para concatenar, no parámetros. Escapa comillas y barras al estilo MySQL, así que solo es seguro contra PostgreSQL con standard_conforming_strings=off — el contrato que PGClient ya fija. Fuera de ese contexto, usa consultas parametrizadas.
Familias de extensiones
El módulo añade cientos de métodos de extensión. Estas son las familias que más se usan.
Vacío y nulos
Un test de vacío/nulo unificado para strings, colecciones, fechas, GUIDs y tipos propios.
IsEmpty(),IsNotEmpty(),HasContent()— sobreString,List,Dictionary,IEnumerable,Guid, fechas anulables.IsNull(),IsNotNull(),NotEmpty()— sobreGuidyObject.OrEmpty()— devuelve una secuencia vacía si el origen esnull(para iterar sin comprobar).IfIsEmpty(valor)— coalescencia a un valor por defecto para números y fechas.
if (report.Rows.IsNotEmpty()) { /* ... */ }
foreach (var x in lista.OrEmpty()) { /* nunca NullReference */ }Predicados de string
Validación y coincidencia sobre texto.
IsEmail(),IsGUID(),IsNumeric(),IsInteger(),IsJson(),IsDateOnly().ContainsWord(),ContainsIgnoreCase(),EqualsIgnoreCase(),StartsWithIgnoreCase(),EndsWithIgnoreCase().MatchAllWords(),MatchPercentage(),ContainsWebSearchMode()— búsqueda por palabras al estilo buscador.
LikeM (comparación múltiple)
Atajo para "¿el valor es igual a alguno de estos?". Elimina los OR anidados. Hay sobrecargas para Integer, Decimal, Guid, Char y String.
if (estado.LikeM(1, 2, 5)) { /* 1, 2 o 5 */ }
if (letra.LikeMIgnoreCase("A", "B", "C")) { /* ... */ }Guardas de argumentos (ThrowIf_)
Cláusulas de guarda que lanzan una excepción descriptiva si el argumento no cumple.
ThrowIf_IsNull(),ThrowIf_IsEmpty()— sobreString, colecciones,Guid, números, fechas.ThrowIf_IsNotGuid(),ThrowIf_IsNotEmail(),ThrowIf_IsNotUrl(),ThrowIf_IsZero().
email.ThrowIf_IsNotEmail(nameof(email));
sectionId.ThrowIf_IsEmpty(nameof(sectionId));Colecciones
GetM(i)— indexado seguro: devuelve el valor por defecto si el índice se sale, en vez de lanzar.HasElements(),HasContent()— presencia sobre arrays, listas y diccionarios.GetRandom(),MoveItemUp(),MoveItemDown(),AddRange()sobreHashSet.
Transformación y numéricas
- String:
RemoveAccents(),RemoveSpecialCharacters(),UppercaseFirst(),ParseBetween(),Trim_PN()(trim seguro con nulos),FormatJson(). - Numéricas:
Between(min, max),IsMultipleOf(),RoundMoney(decimales),Half(),HasDecimalPlaces().
Estas listas son representativas, no exhaustivas: el módulo trae muchas más. Los nombres citados existen en el código; explora por IntelliSense sobre el tipo que estés usando.
Dinaup.Validations
Validaciones listas para usar de datos fiscales y geográficos: NIF/VAT, VIES, AEAT, códigos postales, provincias y países desde tu código .NET.
Almacenamiento S3
Sube, descarga y firma objetos en S3/MinIO desde .NET con DinaS3ClientC, y replica en varios buckets con DinaS3MultiClientC.