Mango.Nop.Libraries/docs/ARCHITECTURE.md

138 lines
7.3 KiB
Markdown

# Architecture
## Dependency Graph
```
AyCode.Core (net9.0, DLL refs: AyCode.Interfaces, .Entities, .Core, .Utils, + .Server variants)
Mango.Nop.Core (net9.0, no nopCommerce runtime dependency)
Mango.Nop.Data (net9.0) → Nop.Core, Nop.Data
Mango.Nop.Services (net9.0) → Nop.Core, Nop.Data, Nop.Services, Nop.Web.Framework
```
**Rule:** Dependencies flow upward only. `Mango.Nop.Core` has zero nopCommerce runtime dependency — it uses mirror copies in `NopDependencies/`.
## Project Roles
### Mango.Nop.Core — Domain Layer
Zero nopCommerce runtime dependency. Contains:
- **DTOs** (`Dtos/`) — `ModelDtoBase<TMainEntity>` with bidirectional entity mapping (`CopyEntityValuesToDto`, `CopyDtoValuesToEntity`, `CreateMainEntity`)
- **Entities** (`Entities/`) — `MgEntityBase` (inherits `BaseEntity`, implements `IEntityInt`)
- **NopDependencies** (`NopDependencies/`) — mirror copies of nopCommerce entities (`BaseEntity`, `Customer`, `Order`, `Product`, `GenericAttribute`, enums). Allows referencing without full nopCommerce dependency chain.
- **Extensions** (`Extensions/`) — `GenericAttributeExtensions` for typed attribute access, `CollectionExtensionsNopBaseEntity` for collection operations
- **Interfaces** (`Interfaces/`) — DTO interfaces, soft-delete, foreign key markers
- **Models** (`Models/`) — Login request/response
- **Loggers** (`Loggers/`) — `ILogger` abstraction wrapping AyCode `IAcLoggerBase`
### Mango.Nop.Data — Data Access Layer
Wraps nopCommerce data infrastructure with custom base classes:
- **`MgDbTableBase<TEntity>`** — extends nopCommerce `EntityRepository<TEntity>`, adds `GetAll()`, timestamp handling (`ITimeStampCreated`, `ITimeStampModified`), event publishing
- **`MgDtoDbTableBase<TDtoEntity, TMainEntity>`** — DTO-aware repository. **Critical: Delete operations throw — must use `DeleteMainEntityById()`.** Event bridging: DTO events → main entity events
- **`MgDbContextBase`** — DB context base with `Transaction/TransactionSafe/TransactionAsync/TransactionSafeAsync` methods. TransactionSafe variants use global `SemaphoreSlim` lock
- **`MgDalBase<TDbContext>`** — Data Access Layer orchestrator with `Context`, `Name`, `MutextLock`
### Mango.Nop.Services — Service Layer
Service base classes for nopCommerce plugin development:
- **`MgBackgroundServiceBase`** — hosted background task with configurable interval, pause support, per-iteration error handling
- **`MgSessionServiceBase<TSessionItem>`** / `MgSessionItemBase` — in-memory session management via `ConcurrentDictionary`, SignalR connection tracking
- **`MgEventConsumerBase`** — nopCommerce entity event handler base (Product insert/update, CustomerRegistered, OrderPlaced, PageRendering, ProductSearch)
- **`MgLockServiceBase`** — `SemaphoreSlim(1)` lock wrapper
- **`NopLogWriter`** — logging bridge: AyCode log levels → nopCommerce `Log` table via direct DB insert with `TransactionScope(Suppress)`
## NopDependencies Pattern
`Mango.Nop.Core/NopDependencies/` contains mirror copies of nopCommerce entity classes with the **same namespace** as the original nopCommerce types:
```csharp
// In NopDependencies/BaseEntity.cs — same namespace as nopCommerce
namespace Nop.Core;
public abstract partial class BaseEntity : IBaseEntity
{
public int Id { get; set; }
}
```
This allows `Mango.Nop.Core` to be referenced by projects that don't have a direct nopCommerce dependency (e.g., Blazor/MAUI clients), while maintaining type compatibility with the real nopCommerce entities at the server level.
**Files in NopDependencies:**
- `BaseEntity.cs` + `IBaseEntity` — root entity base (`Nop.Core`)
- `Catalogs/``Customer`, `CustomerRole`, `Order`, `OrderItem`, `OrderNote`, `Product`, `GenericAttribute`, `StockQuantityHistory`, `DiscountMapping`, `DiscountProductMapping`
- Enums — `OrderStatus`, `PaymentStatus`, `ShippingStatus`, `ProductType`, `ManageInventoryMethod`, `BackorderMode`, `LowStockActivity`, `GiftCardType`, `RentalPricePeriod`, `RecurringProductCyclePeriod`, `DownloadActivationType`, `TaxDisplayType`, `VatNumberStatus`
- Interfaces — `ISoftDeletedEntity`, `ILocalizedEntity`, `ISlugSupported`, `IAclSupported`, `IStoreMappingSupported`, `IDiscountSupported`
## DTO Mapping Strategies
Two patterns coexist:
### Strategy 1: `ModelDtoBase<T>` (simple DTOs)
Used by: `CustomerDto`, `MgGenericAttributeDto`
```
ModelDtoBase → ModelDtoBase<Customer> → CustomerDto
```
- Manual `CopyEntityValuesToDto`/`CopyDtoValuesToEntity` overrides
- No LinqToDB associations
### Strategy 2: `MgEntityBase` + `IModelDtoBase<T>` (complex DTOs)
Used by: `MgOrderDto`, `MgOrderItemDto`, `MgStockQuantityHistoryDto`
```
BaseEntity → MgEntityBase → MgOrderDto<TOrderItemDto, TProductDto> : IModelDtoBase<Order>
```
- Uses `PropertyHelper.CopyPublicValueTypeProperties()` for bulk copy
- LinqToDB `[Association]` navigation properties
- Generic type parameters for child DTOs
### Strategy 3: Entity inheritance (MgProductDto)
```
BaseEntity → MgEntityBase → MgProductDto : IMgProductDto
```
- No `IModelDtoBase<Product>` (entity mapping methods are commented out)
- Direct property declarations mirroring `Product` fields
## Transaction Pattern
`MgDbContextBase` provides 4 transaction methods:
| Method | Lock | Async |
|---|---|---|
| `Transaction(callback)` | No | No |
| `TransactionSafe(callback)` | `SemaphoreSlim` | No |
| `TransactionAsync(callback)` | No | Yes (thread pool) |
| `TransactionSafeAsync(callback)` | `SemaphoreSlim` | Yes (thread pool) |
**Callback contract:** `Func<TransactionScope, (Task<)bool(>)>` — return `true` to commit, `false` to rollback.
**Isolation level:** `ReadCommitted`
**Error handling:** Catches exceptions, logs, returns `false` (unless `throwException = true`)
## Logging Architecture
Base logging infrastructure (`IAcLoggerBase`, `IAcLogWriterBase`, `AcLoggerBase`, `AcLogItemWriterBase`, `AcLogItem`) is defined in AyCode.Core — see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md` for base types, log levels, and writer contracts.
This layer provides the nopCommerce-specific bridge:
```
Application code → Mango.Nop.Core.Loggers.ILogger (extends IAcLoggerBase)
→ Logger<TCategory> (extends AcLoggerBase, delegates to IAcLogWriterBase[])
→ NopLogWriter (in Services, extends AcLogItemWriterBase<AcLogItem>) → Nop Log table (direct SQL insert)
→ [Other AyCode log writers: console, file, SignalR, etc. — see AyCode.Core/AyCode.Core/docs/LOGGING/README.md]
```
**Important:** `MgBackgroundServiceBase` uses nopCommerce's `Nop.Services.Logging.ILogger` directly (not the Mango wrapper). Other services use `Mango.Nop.Core.Loggers.ILogger`.
## Reference Modes
```
Mango.Nop Libraries
┌──────────────────────┐
│ Core Data Services │
└──┬──────┬──────┬─────┘
│ │ │
┌───────────────┤ │ │
│ (DLL, Core │ │ │
│ only) │ │ │
▼ ▼ ▼ ▼
Types-only clients Full-stack nopCommerce
(Blazor/MAUI/etc.) plugins (server-side)
```