(feature): sagas Ilogger improvements, documentation
This commit is contained in:
parent
224b38b408
commit
cb83909ba2
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Maksym Sadovnychyy (MAKS-IT)
|
||||
Copyright (c) 2024 - 2025 Maksym Sadovnychyy (MAKS-IT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@ -10,7 +10,7 @@ namespace MaksIT.Core.Extensions.Tests;
|
||||
string outputTarPath = "output.tar";
|
||||
|
||||
// Act
|
||||
bool result = FromatsExtensions.TryCreateTarFromDirectory(invalidSourceDirectory, outputTarPath);
|
||||
bool result = FormatsExtensions.TryCreateTarFromDirectory(invalidSourceDirectory, outputTarPath);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
@ -23,7 +23,7 @@ namespace MaksIT.Core.Extensions.Tests;
|
||||
string invalidOutputPath = "";
|
||||
|
||||
// Act
|
||||
bool result = FromatsExtensions.TryCreateTarFromDirectory(sourceDirectory, invalidOutputPath);
|
||||
bool result = FormatsExtensions.TryCreateTarFromDirectory(sourceDirectory, invalidOutputPath);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
@ -37,7 +37,7 @@ namespace MaksIT.Core.Extensions.Tests;
|
||||
string outputTarPath = Path.Combine(Path.GetTempPath(), "output.tar");
|
||||
|
||||
// Act
|
||||
bool result = FromatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
|
||||
bool result = FormatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
@ -57,7 +57,7 @@ namespace MaksIT.Core.Extensions.Tests;
|
||||
string outputTarPath = Path.Combine(Path.GetTempPath(), "output.tar");
|
||||
|
||||
// Act
|
||||
bool result = FromatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
|
||||
bool result = FormatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
@ -82,7 +82,7 @@ namespace MaksIT.Core.Extensions.Tests;
|
||||
// Lock the file to simulate inability to create it
|
||||
using (FileStream lockedFile = File.Create(outputTarPath)) {
|
||||
// Act
|
||||
bool result = FromatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
|
||||
bool result = FormatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
||||
@ -11,7 +11,7 @@ public class LocalSagaTests
|
||||
{
|
||||
// Arrange
|
||||
var logger = LoggerHelper.CreateConsoleLogger();
|
||||
var builder = new LocalSagaBuilder().WithLogger(logger);
|
||||
var builder = new LocalSagaBuilder(logger);
|
||||
var stepExecuted = false;
|
||||
|
||||
builder.AddAction(
|
||||
@ -36,7 +36,7 @@ public class LocalSagaTests
|
||||
{
|
||||
// Arrange
|
||||
var logger = LoggerHelper.CreateConsoleLogger();
|
||||
var builder = new LocalSagaBuilder().WithLogger(logger);
|
||||
var builder = new LocalSagaBuilder(logger);
|
||||
var compensationCalled = false;
|
||||
|
||||
builder.AddAction(
|
||||
@ -63,7 +63,7 @@ public class LocalSagaTests
|
||||
{
|
||||
// Arrange
|
||||
var logger = LoggerHelper.CreateConsoleLogger();
|
||||
var builder = new LocalSagaBuilder().WithLogger(logger);
|
||||
var builder = new LocalSagaBuilder(logger);
|
||||
var stepExecuted = false;
|
||||
|
||||
builder.AddActionIf(
|
||||
@ -89,7 +89,7 @@ public class LocalSagaTests
|
||||
{
|
||||
// Arrange
|
||||
var logger = LoggerHelper.CreateConsoleLogger();
|
||||
var builder = new LocalSagaBuilder().WithLogger(logger);
|
||||
var builder = new LocalSagaBuilder(logger);
|
||||
|
||||
builder.AddAction(
|
||||
"LoggingStep",
|
||||
@ -107,7 +107,7 @@ public class LocalSagaTests
|
||||
{
|
||||
// Arrange
|
||||
var logger = LoggerHelper.CreateConsoleLogger();
|
||||
var builder = new LocalSagaBuilder().WithLogger(logger);
|
||||
var builder = new LocalSagaBuilder(logger);
|
||||
var context = new LocalSagaContext();
|
||||
context.Set("state", "initial");
|
||||
|
||||
@ -143,7 +143,7 @@ public class LocalSagaTests
|
||||
{
|
||||
// Arrange
|
||||
var logger = LoggerHelper.CreateConsoleLogger();
|
||||
var builder = new LocalSagaBuilder().WithLogger(logger);
|
||||
var builder = new LocalSagaBuilder(logger);
|
||||
var context = new LocalSagaContext();
|
||||
var compensationLog = new List<string>();
|
||||
|
||||
|
||||
@ -4,12 +4,13 @@
|
||||
namespace MaksIT.Core.Extensions;
|
||||
public static class DataTableExtensions {
|
||||
|
||||
/// <summary>
|
||||
/// Counts duplicate records between two DataTables.
|
||||
/// </summary>
|
||||
/// <param name="dt1"></param>
|
||||
/// <param name="dt2"></param>
|
||||
/// <returns></returns>
|
||||
public static int DuplicatesCount(this DataTable dt1, DataTable dt2) {
|
||||
if (dt1 == null)
|
||||
throw new ArgumentNullException(nameof(dt1));
|
||||
if (dt2 == null)
|
||||
throw new ArgumentNullException(nameof(dt2));
|
||||
|
||||
var duplicates = 0;
|
||||
foreach (DataRow dtRow1 in dt1.Rows) {
|
||||
var dt1Items = dtRow1.ItemArray.Select(item => item?.ToString() ?? string.Empty);
|
||||
@ -34,11 +35,6 @@ public static class DataTableExtensions {
|
||||
/// <param name="columns"></param>
|
||||
/// <returns></returns>
|
||||
public static DataTable DistinctRecords(this DataTable dt, string[] columns) {
|
||||
if (dt == null)
|
||||
throw new ArgumentNullException(nameof(dt));
|
||||
if (columns == null)
|
||||
throw new ArgumentNullException(nameof(columns));
|
||||
|
||||
return dt.DefaultView.ToTable(true, columns);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,14 @@
|
||||
namespace MaksIT.Core.Extensions;
|
||||
|
||||
public static class DateTimeExtensions {
|
||||
|
||||
/// <summary>
|
||||
/// Adds workdays to a given date, skipping weekends and holidays defined in the holiday calendar.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <param name="days"></param>
|
||||
/// <param name="holidayCalendar"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime AddWorkdays(this DateTime date, int days, IHolidayCalendar holidayCalendar) {
|
||||
if (days == 0)
|
||||
return date;
|
||||
@ -28,21 +36,45 @@ public static class DateTimeExtensions {
|
||||
return currentDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds workdays to a given date, skipping weekends and holidays defined in the holiday calendar.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <param name="timeSpanWorkDays"></param>
|
||||
/// <param name="holidayCalendar"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime AddWorkdays(this DateTime date, TimeSpan timeSpanWorkDays, IHolidayCalendar holidayCalendar) =>
|
||||
date.AddWorkdays(timeSpanWorkDays.Days, holidayCalendar);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the next specified weekday from the given start date.
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="day"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime NextWeekday(this DateTime start, DayOfWeek day) {
|
||||
int daysToAdd = ((int)day - (int)start.DayOfWeek + 7) % 7;
|
||||
daysToAdd = daysToAdd == 0 ? 7 : daysToAdd; // If today is the target day, move to next week
|
||||
return start.AddDays(daysToAdd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the TimeSpan to the next specified weekday from the given start date.
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="day"></param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan ToNextWeekday(this DateTime start, DayOfWeek day) {
|
||||
int daysToAdd = ((int)day - (int)start.DayOfWeek + 7) % 7;
|
||||
daysToAdd = daysToAdd == 0 ? 7 : daysToAdd;
|
||||
return TimeSpan.FromDays(daysToAdd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the next end of month from the given date.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime NextEndOfMonth(this DateTime date) {
|
||||
var nextMonth = date.AddMonths(1);
|
||||
return new DateTime(
|
||||
@ -55,6 +87,11 @@ public static class DateTimeExtensions {
|
||||
date.Kind);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the end of month for the given date.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime EndOfMonth(this DateTime date) =>
|
||||
new DateTime(
|
||||
date.Year,
|
||||
@ -65,29 +102,70 @@ public static class DateTimeExtensions {
|
||||
date.Second,
|
||||
date.Kind);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the begin of month for the given date.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime BeginOfMonth(this DateTime date) =>
|
||||
new DateTime(date.Year, date.Month, 1, date.Hour, date.Minute, date.Second, date.Kind);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the start of year for the given date.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime StartOfYear(this DateTime date) =>
|
||||
new DateTime(date.Year, 1, 1, date.Hour, date.Minute, date.Second, date.Kind);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the end of year for the given date.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime EndOfYear(this DateTime date) =>
|
||||
new DateTime(date.Year, 12, 31, date.Hour, date.Minute, date.Second, date.Kind);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given date is the end of the month.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsEndOfMonth(this DateTime date) =>
|
||||
date.Day == DateTime.DaysInMonth(date.Year, date.Month);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given date is the begin of the month.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsBeginOfMonth(this DateTime date) => date.Day == 1;
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given date is the end of the year.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsEndOfYear(this DateTime date) => date.Day == 31 && date.Month == 12;
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given date is the begin of the year.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <param name="targetDate"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsSameMonth(this DateTime date, DateTime targetDate) =>
|
||||
date.Month == targetDate.Month && date.Year == targetDate.Year;
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the difference in complete years between two dates.
|
||||
/// Implementation follows the logic used in Excel's DATEDIF function
|
||||
/// "COMPLETE calendar years in between dates"
|
||||
/// </summary>
|
||||
/// <param name="startDate"></param>
|
||||
/// <param name="endDate"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetDifferenceInYears(this DateTime startDate, DateTime endDate) {
|
||||
// Implementation follows the logic used in Excel's DATEDIF function
|
||||
// "COMPLETE calendar years in between dates"
|
||||
|
||||
int years = endDate.Year - startDate.Year;
|
||||
|
||||
if (endDate.Month < startDate.Month ||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
namespace MaksIT.Core.Extensions;
|
||||
public static class FromatsExtensions {
|
||||
public static class FormatsExtensions {
|
||||
public static bool TryCreateTarFromDirectory(string sourceDirectory, string outputTarPath) {
|
||||
// Validate source directory
|
||||
if (string.IsNullOrWhiteSpace(sourceDirectory) || !Directory.Exists(sourceDirectory)) {
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
<!-- NuGet package metadata -->
|
||||
<PackageId>MaksIT.Core</PackageId>
|
||||
<Version>1.4.8</Version>
|
||||
<Version>1.4.9</Version>
|
||||
<Authors>Maksym Sadovnychyy</Authors>
|
||||
<Company>MAKS-IT</Company>
|
||||
<Product>MaksIT.Core</Product>
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
namespace MaksIT.Core.Sagas;
|
||||
/// <summary>
|
||||
@ -15,7 +11,8 @@ public sealed class LocalSaga {
|
||||
|
||||
internal LocalSaga(
|
||||
IReadOnlyList<ILocalSagaStep> pipeline,
|
||||
ILogger logger) {
|
||||
ILogger logger
|
||||
) {
|
||||
_pipeline = pipeline;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
namespace MaksIT.Core.Sagas;
|
||||
|
||||
@ -12,11 +8,10 @@ namespace MaksIT.Core.Sagas;
|
||||
/// </summary>
|
||||
public sealed class LocalSagaBuilder {
|
||||
private readonly List<ILocalSagaStep> _pipeline = new();
|
||||
private ILogger? _logger;
|
||||
private ILogger _logger;
|
||||
|
||||
public LocalSagaBuilder WithLogger(ILogger logger) {
|
||||
public LocalSagaBuilder (ILogger logger) {
|
||||
_logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LocalSagaBuilder AddAction(
|
||||
@ -66,8 +61,6 @@ public sealed class LocalSagaBuilder {
|
||||
}
|
||||
|
||||
public LocalSaga Build() {
|
||||
if (_logger == null)
|
||||
throw new InvalidOperationException("Logger must be provided via WithLogger().");
|
||||
return new LocalSaga(_pipeline, _logger);
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Core.Sagas;
|
||||
namespace MaksIT.Core.Sagas;
|
||||
|
||||
/// <summary>
|
||||
/// Shared context to pass values between steps without tight coupling.
|
||||
|
||||
@ -1,11 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace MaksIT.Core.Sagas;
|
||||
namespace MaksIT.Core.Sagas;
|
||||
|
||||
/// <summary>
|
||||
/// Internal non-generic step interface to unify generic steps.
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
namespace MaksIT.Core.Sagas;
|
||||
|
||||
namespace MaksIT.Core.Sagas;
|
||||
/// <summary>
|
||||
/// A simple unit type for steps that do not return a value.
|
||||
/// </summary>
|
||||
|
||||
811
src/README.md
811
src/README.md
@ -1,811 +0,0 @@
|
||||
# MaksIT.Core Library Documentation
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Abstractions](#abstractions)
|
||||
- [Base Classes](#base-classes)
|
||||
- [Enumeration](#enumeration)
|
||||
- [Extensions](#extensions)
|
||||
- [Expression Extensions](#expression-extensions)
|
||||
- [DateTime Extensions](#datetime-extensions)
|
||||
- [String Extensions](#string-extensions)
|
||||
- [Object Extensions](#object-extensions)
|
||||
- [DataTable Extensions](#datatable-extensions)
|
||||
- [Guid Extensions](#guid-extensions)
|
||||
- [Logging](#logging)
|
||||
- [Networking](#networking)
|
||||
- [Network Connection](#network-connection)
|
||||
- [Ping Port](#ping-port)
|
||||
- [Security](#security)
|
||||
- [AES-GCM Utility](#aes-gcm-utility)
|
||||
- [Base32 Encoder](#base32-encoder)
|
||||
- [Checksum Utility](#checksum-utility)
|
||||
- [Password Hasher](#password-hasher)
|
||||
- [JWT Generator](#jwt-generator)
|
||||
- [TOTP Generator](#totp-generator)
|
||||
- [Web API Models](#web-api-models)
|
||||
- [Sagas](#sagas)
|
||||
- [Others](#others)
|
||||
- [Culture](#culture)
|
||||
- [Environment Variables](#environment-variables)
|
||||
- [File System](#file-system)
|
||||
- [Processes](#processes)
|
||||
|
||||
|
||||
## Abstractions
|
||||
|
||||
### Base Classes
|
||||
|
||||
The following base classes in the `MaksIT.Core.Abstractions` namespace provide a foundation for implementing domain, DTO, and Web API models, ensuring consistency and maintainability in application design.
|
||||
|
||||
---
|
||||
|
||||
##### 1. **`DomainObjectBase`**
|
||||
|
||||
###### Summary
|
||||
Represents the base class for all domain objects in the application.
|
||||
|
||||
###### Purpose
|
||||
- Serves as the foundation for all domain objects.
|
||||
- Provides a place to include shared logic or properties for domain-level entities in the future.
|
||||
|
||||
---
|
||||
|
||||
##### 2. **`DomainDocumentBase<T>`**
|
||||
|
||||
###### Summary
|
||||
Represents a base class for domain documents with a unique identifier.
|
||||
|
||||
###### Purpose
|
||||
- Extends `DomainObjectBase` to include an identifier.
|
||||
- Provides a common structure for domain entities that need unique IDs.
|
||||
|
||||
###### Example Usage
|
||||
```csharp
|
||||
public class UserDomainDocument : DomainDocumentBase<Guid> {
|
||||
public UserDomainDocument(Guid id) : base(id) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
##### 3. **`DtoObjectBase`**
|
||||
|
||||
###### Summary
|
||||
Represents the base class for all Data Transfer Objects (DTOs).
|
||||
|
||||
###### Purpose
|
||||
- Serves as the foundation for all DTOs.
|
||||
- Provides a place to include shared logic or properties for DTOs in the future.
|
||||
|
||||
---
|
||||
|
||||
##### 4. **`DtoDocumentBase<T>`**
|
||||
|
||||
###### Summary
|
||||
Represents a base class for DTOs with a unique identifier.
|
||||
|
||||
###### Purpose
|
||||
- Extends `DtoObjectBase` to include an identifier.
|
||||
- Provides a common structure for DTOs that need unique IDs.
|
||||
|
||||
###### Example Usage
|
||||
```csharp
|
||||
public class UserDto : DtoDocumentBase<Guid> {
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
##### 5. **`RequestModelBase`**
|
||||
|
||||
###### Summary
|
||||
Represents the base class for Web API request models.
|
||||
|
||||
###### Purpose
|
||||
- Serves as a foundation for request models used in Web API endpoints.
|
||||
- Provides a common structure for request validation or shared properties.
|
||||
|
||||
###### Example Usage
|
||||
```csharp
|
||||
public class CreateUserRequest : RequestModelBase {
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
##### 6. **`ResponseModelBase`**
|
||||
|
||||
###### Summary
|
||||
Represents the base class for Web API response models.
|
||||
|
||||
###### Purpose
|
||||
- Serves as a foundation for response models returned by Web API endpoints.
|
||||
- Provides a common structure for standardizing API responses.
|
||||
|
||||
###### Example Usage
|
||||
```csharp
|
||||
public class UserResponse : ResponseModelBase {
|
||||
public required Guid Id { get; set; }
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Features and Benefits
|
||||
|
||||
1. **Consistency**:
|
||||
- Ensures a uniform structure for domain, DTO, and Web API models.
|
||||
|
||||
2. **Extensibility**:
|
||||
- Base classes can be extended to include shared properties or methods as needed.
|
||||
|
||||
3. **Type Safety**:
|
||||
- Generic identifiers (`T`) ensure type safety for domain documents and DTOs.
|
||||
|
||||
4. **Reusability**:
|
||||
- Common logic or properties can be added to base classes and reused across the application.
|
||||
|
||||
---
|
||||
|
||||
#### Example End-to-End Usage
|
||||
|
||||
```csharp
|
||||
// Domain Class
|
||||
public class ProductDomain : DomainDocumentBase<int> {
|
||||
public ProductDomain(int id) : base(id) { }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
// DTO Class
|
||||
public class ProductDto : DtoDocumentBase<int> {
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
|
||||
// Web API Request Model
|
||||
public class CreateProductRequest : RequestModelBase {
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
|
||||
// Web API Response Model
|
||||
public class ProductResponse : ResponseModelBase {
|
||||
public required int Id { get; set; }
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Best Practices
|
||||
|
||||
1. **Keep Base Classes Lightweight**:
|
||||
- Avoid adding unnecessary properties or methods to base classes.
|
||||
|
||||
2. **Encapsulation**:
|
||||
- Use base classes to enforce encapsulation and shared behavior across entities.
|
||||
|
||||
3. **Validation**:
|
||||
- Extend `RequestModelBase` or `ResponseModelBase` to include validation logic if needed.
|
||||
|
||||
---
|
||||
|
||||
This structure promotes clean code principles, reducing redundancy and improving maintainability across the application layers.
|
||||
|
||||
---
|
||||
|
||||
### Enumeration
|
||||
|
||||
The `Enumeration` class in the `MaksIT.Core.Abstractions` namespace provides a base class for creating strongly-typed enumerations. It enables you to define enumerable constants with additional functionality, such as methods for querying, comparing, and parsing enumerations.
|
||||
|
||||
---
|
||||
|
||||
#### Features and Benefits
|
||||
|
||||
1. **Strongly-Typed Enumerations**:
|
||||
- Combines the clarity of enums with the extensibility of classes.
|
||||
- Supports additional fields, methods, or logic as needed.
|
||||
|
||||
2. **Reflection Support**:
|
||||
- Dynamically retrieve all enumeration values with `GetAll`.
|
||||
|
||||
3. **Parsing Capabilities**:
|
||||
- Retrieve enumeration values by ID or display name.
|
||||
|
||||
4. **Comparison and Equality**:
|
||||
- Fully implements equality and comparison operators for use in collections and sorting.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
#### Defining an Enumeration
|
||||
```csharp
|
||||
public class MyEnumeration : Enumeration {
|
||||
public static readonly MyEnumeration Value1 = new(1, "Value One");
|
||||
public static readonly MyEnumeration Value2 = new(2, "Value Two");
|
||||
|
||||
private MyEnumeration(int id, string name) : base(id, name) { }
|
||||
}
|
||||
```
|
||||
|
||||
#### Retrieving All Values
|
||||
```csharp
|
||||
var allValues = Enumeration.GetAll<MyEnumeration>();
|
||||
allValues.ToList().ForEach(Console.WriteLine);
|
||||
```
|
||||
|
||||
#### Parsing by ID or Name
|
||||
```csharp
|
||||
var valueById = Enumeration.FromValue<MyEnumeration>(1);
|
||||
var valueByName = Enumeration.FromDisplayName<MyEnumeration>("Value One");
|
||||
|
||||
Console.WriteLine(valueById); // Output: Value One
|
||||
Console.WriteLine(valueByName); // Output: Value One
|
||||
```
|
||||
|
||||
#### Comparing Enumeration Values
|
||||
```csharp
|
||||
var difference = Enumeration.AbsoluteDifference(MyEnumeration.Value1, MyEnumeration.Value2);
|
||||
Console.WriteLine($"Absolute Difference: {difference}"); // Output: 1
|
||||
```
|
||||
|
||||
#### Using in Collections
|
||||
```csharp
|
||||
var values = new List<MyEnumeration> { MyEnumeration.Value2, MyEnumeration.Value1 };
|
||||
values.Sort(); // Orders by ID
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Best Practices
|
||||
|
||||
1. **Extend for Specific Enums**:
|
||||
- Create specific subclasses for each enumeration type.
|
||||
|
||||
2. **Avoid Duplicates**:
|
||||
- Ensure unique IDs and names for each enumeration value.
|
||||
|
||||
3. **Use Reflection Sparingly**:
|
||||
- Avoid calling `GetAll` in performance-critical paths.
|
||||
|
||||
---
|
||||
|
||||
The `Enumeration` class provides a powerful alternative to traditional enums, offering flexibility and functionality for scenarios requiring additional metadata or logic.
|
||||
|
||||
---
|
||||
|
||||
### Extensions
|
||||
|
||||
### Guid Extensions
|
||||
|
||||
The `GuidExtensions` class provides methods for working with `Guid` values, including converting them to nullable types.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Convert to Nullable**:
|
||||
- Convert a `Guid` to a nullable `Guid?`, returning `null` if the `Guid` is empty.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Converting to Nullable
|
||||
```csharp
|
||||
Guid id = Guid.NewGuid();
|
||||
Guid? nullableId = id.ToNullable();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Expression Extensions
|
||||
|
||||
The `ExpressionExtensions` class provides utility methods for combining and manipulating LINQ expressions. These methods are particularly useful for building dynamic queries in a type-safe manner.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Combine Expressions**:
|
||||
- Combine two expressions using logical operators like `AndAlso` and `OrElse`.
|
||||
|
||||
2. **Negate Expressions**:
|
||||
- Negate an expression using the `Not` method.
|
||||
|
||||
3. **Batch Processing**:
|
||||
- Divide a collection into smaller batches for processing.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Combining Expressions
|
||||
```csharp
|
||||
Expression<Func<int, bool>> isEven = x => x % 2 == 0;
|
||||
Expression<Func<int, bool>> isPositive = x => x > 0;
|
||||
|
||||
var combined = isEven.AndAlso(isPositive);
|
||||
var result = combined.Compile()(4); // True
|
||||
```
|
||||
|
||||
##### Negating Expressions
|
||||
```csharp
|
||||
Expression<Func<int, bool>> isEven = x => x % 2 == 0;
|
||||
var notEven = isEven.Not();
|
||||
var result = notEven.Compile()(3); // True
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### DateTime Extensions
|
||||
|
||||
The `DateTimeExtensions` class provides methods for manipulating and querying `DateTime` objects. These methods simplify common date-related operations.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Add Workdays**:
|
||||
- Add a specified number of workdays to a date, excluding weekends and holidays.
|
||||
|
||||
2. **Find Specific Dates**:
|
||||
- Find the next occurrence of a specific day of the week.
|
||||
|
||||
3. **Month and Year Boundaries**:
|
||||
- Get the start or end of the current month or year.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Adding Workdays
|
||||
```csharp
|
||||
DateTime today = DateTime.Today;
|
||||
DateTime futureDate = today.AddWorkdays(5);
|
||||
```
|
||||
|
||||
##### Finding the Next Monday
|
||||
```csharp
|
||||
DateTime today = DateTime.Today;
|
||||
DateTime nextMonday = today.NextWeekday(DayOfWeek.Monday);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### String Extensions
|
||||
|
||||
The `StringExtensions` class provides a wide range of methods for string manipulation, validation, and conversion.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Pattern Matching**:
|
||||
- Check if a string matches a pattern using SQL-like wildcards.
|
||||
|
||||
2. **Substring Extraction**:
|
||||
- Extract substrings from the left, right, or middle of a string.
|
||||
|
||||
3. **Type Conversion**:
|
||||
- Convert strings to various types, such as integers, booleans, and enums.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Pattern Matching
|
||||
```csharp
|
||||
bool matches = "example".Like("exa*e"); // True
|
||||
```
|
||||
|
||||
##### Substring Extraction
|
||||
```csharp
|
||||
string result = "example".Left(3); // "exa"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Object Extensions
|
||||
|
||||
The `ObjectExtensions` class provides methods for serializing objects to JSON strings and deserializing JSON strings back to objects.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **JSON Serialization**:
|
||||
- Convert objects to JSON strings.
|
||||
|
||||
2. **JSON Deserialization**:
|
||||
- Convert JSON strings back to objects.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Serialization
|
||||
```csharp
|
||||
var person = new { Name = "John", Age = 30 };
|
||||
string json = person.ToJson();
|
||||
```
|
||||
|
||||
##### Deserialization
|
||||
```csharp
|
||||
var person = json.ToObject<Person>();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### DataTable Extensions
|
||||
|
||||
The `DataTableExtensions` class provides methods for working with `DataTable` objects, such as counting duplicate rows and retrieving distinct records.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Count Duplicates**:
|
||||
- Count duplicate rows between two `DataTable` instances.
|
||||
|
||||
2. **Retrieve Distinct Records**:
|
||||
- Get distinct rows based on specified columns.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Counting Duplicates
|
||||
```csharp
|
||||
int duplicateCount = table1.DuplicatesCount(table2);
|
||||
```
|
||||
|
||||
##### Retrieving Distinct Records
|
||||
```csharp
|
||||
DataTable distinctTable = table.DistinctRecords(new[] { "Name", "Age" });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Logging
|
||||
|
||||
The `Logging` namespace provides a custom file-based logging implementation that integrates with the `Microsoft.Extensions.Logging` framework.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **File-Based Logging**:
|
||||
- Log messages to a specified file.
|
||||
|
||||
2. **Log Levels**:
|
||||
- Supports all standard log levels.
|
||||
|
||||
3. **Thread Safety**:
|
||||
- Ensures thread-safe writes to the log file.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
```csharp
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging(builder => builder.AddFile("logs.txt"));
|
||||
|
||||
var logger = services.BuildServiceProvider().GetRequiredService<ILogger<FileLogger>>();
|
||||
logger.LogInformation("Logging to file!");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Networking
|
||||
|
||||
### Network Connection
|
||||
|
||||
The `NetworkConnection` class provides methods for managing connections to network shares on Windows.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Connect to Network Shares**:
|
||||
- Establish connections to shared network resources.
|
||||
|
||||
2. **Error Handling**:
|
||||
- Provides detailed error messages for connection failures.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
```csharp
|
||||
var credentials = new NetworkCredential("username", "password");
|
||||
if (NetworkConnection.TryCreate(logger, "\\server\share", credentials, out var connection, out var error)) {
|
||||
connection.Dispose();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Ping Port
|
||||
|
||||
The `PingPort` class provides methods for checking the reachability of a host on specified TCP or UDP ports.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **TCP Port Checking**:
|
||||
- Check if a TCP port is reachable.
|
||||
|
||||
2. **UDP Port Checking**:
|
||||
- Check if a UDP port is reachable.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Checking a TCP Port
|
||||
```csharp
|
||||
if (PingPort.TryHostPort("example.com", 80, out var error)) {
|
||||
Console.WriteLine("Port is reachable.");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
### AES-GCM Utility
|
||||
|
||||
The `AESGCMUtility` class provides methods for encrypting and decrypting data using AES-GCM.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Secure Encryption**:
|
||||
- Encrypt data with AES-GCM.
|
||||
|
||||
2. **Data Integrity**:
|
||||
- Ensure data integrity with authentication tags.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Encrypting Data
|
||||
```csharp
|
||||
var key = AESGCMUtility.GenerateKeyBase64();
|
||||
AESGCMUtility.TryEncryptData(data, key, out var encryptedData, out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Base32 Encoder
|
||||
|
||||
The `Base32Encoder` class provides methods for encoding and decoding data in Base32 format.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Encoding**:
|
||||
- Encode binary data to Base32.
|
||||
|
||||
2. **Decoding**:
|
||||
- Decode Base32 strings to binary data.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Encoding Data
|
||||
```csharp
|
||||
Base32Encoder.TryEncode(data, out var encoded, out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Checksum Utility
|
||||
|
||||
The `ChecksumUtility` class provides methods for calculating and verifying CRC32 checksums.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Checksum Calculation**:
|
||||
- Calculate CRC32 checksums for data.
|
||||
|
||||
2. **Checksum Verification**:
|
||||
- Verify data integrity using CRC32 checksums.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Calculating a Checksum
|
||||
```csharp
|
||||
ChecksumUtility.TryCalculateCRC32Checksum(data, out var checksum, out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Password Hasher
|
||||
|
||||
The `PasswordHasher` class provides methods for securely hashing and validating passwords.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Salted Hashing**:
|
||||
- Hash passwords with a unique salt.
|
||||
|
||||
2. **Validation**:
|
||||
- Validate passwords against stored hashes.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Hashing a Password
|
||||
```csharp
|
||||
PasswordHasher.TryCreateSaltedHash("password", out var hash, out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### JWT Generator
|
||||
|
||||
The `JwtGenerator` class provides methods for generating and validating JSON Web Tokens (JWTs).
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Token Generation**:
|
||||
- Generate JWTs with claims and metadata.
|
||||
|
||||
2. **Token Validation**:
|
||||
- Validate JWTs against a secret.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Generating a Token
|
||||
```csharp
|
||||
JwtGenerator.TryGenerateToken(secret, issuer, audience, 60, "user", roles, out var token, out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### TOTP Generator
|
||||
|
||||
The `TotpGenerator` class provides methods for generating and validating Time-Based One-Time Passwords (TOTP).
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **TOTP Generation**:
|
||||
- Generate TOTPs based on shared secrets.
|
||||
|
||||
2. **TOTP Validation**:
|
||||
- Validate TOTPs with time tolerance.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Generating a TOTP
|
||||
```csharp
|
||||
TotpGenerator.TryGenerate(secret, TotpGenerator.GetCurrentTimeStepNumber(), out var totp, out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Others
|
||||
|
||||
### Culture
|
||||
|
||||
The `Culture` class provides methods for dynamically setting the culture for the current thread.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Dynamic Culture Setting**:
|
||||
- Change the culture for the current thread.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Setting the Culture
|
||||
```csharp
|
||||
Culture.TrySet("fr-FR", out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables
|
||||
|
||||
The `EnvVar` class provides methods for managing environment variables.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Add to PATH**:
|
||||
- Add directories to the `PATH` environment variable.
|
||||
|
||||
2. **Set and Unset Variables**:
|
||||
- Manage environment variables at different scopes.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Adding to PATH
|
||||
```csharp
|
||||
EnvVar.TryAddToPath("/usr/local/bin", out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### File System
|
||||
|
||||
The `FileSystem` class provides methods for working with files and directories.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Copy Files and Folders**:
|
||||
- Copy files or directories to a target location.
|
||||
|
||||
2. **Delete Files and Folders**:
|
||||
- Delete files or directories.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Copying Files
|
||||
```csharp
|
||||
FileSystem.TryCopyToFolder("source", "destination", true, out var error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Processes
|
||||
|
||||
The `Processes` class provides methods for managing system processes.
|
||||
|
||||
---
|
||||
|
||||
#### Features
|
||||
|
||||
1. **Start Processes**:
|
||||
- Start new processes with optional arguments.
|
||||
|
||||
2. **Kill Processes**:
|
||||
- Terminate processes by name.
|
||||
|
||||
---
|
||||
|
||||
#### Example Usage
|
||||
|
||||
##### Starting a Process
|
||||
```csharp
|
||||
Processes.TryStart("notepad.exe", "", 0, false, out var error);
|
||||
```
|
||||
|
||||
---
|
||||
Loading…
Reference in New Issue
Block a user