48 lines
5.6 KiB
Markdown
48 lines
5.6 KiB
Markdown
# Mango.Nop Libraries — Domain Rules
|
|
|
|
@repo {
|
|
type = "framework"
|
|
layer = 1
|
|
own-dep-repos = ["AyCode.Core"]
|
|
}
|
|
|
|
> This is the **single source of truth** for Mango.Nop library rules. Do not duplicate these elsewhere.
|
|
> For detailed docs see: `README.md` → `docs/`
|
|
> For core framework rules see: `.github/copilot-instructions.md` (in AyCode.Core repo)
|
|
|
|
## nopCommerce Compatibility
|
|
1. All three libraries target **net9.0** — required by nopCommerce 4.80.9. Do NOT change TFM.
|
|
2. **NopDependencies** folder in `Mango.Nop.Core` contains **mirror copies** of nopCommerce entity classes (`BaseEntity`, `Customer`, `Order`, `Product`, `GenericAttribute`, etc.) so that `Mango.Nop.Core` can be referenced without the full nopCommerce dependency chain.
|
|
3. Do NOT modify files in `NopDependencies/` unless the nopCommerce version changes.
|
|
|
|
## Entity & DTO Patterns
|
|
4. **`BaseEntity`** (NopDependencies) = root entity base with `int Id` and `IBaseEntity` interface. All nopCommerce entities inherit from this. Namespace: `Nop.Core`.
|
|
5. **`MgEntityBase`** = custom entity base that inherits `BaseEntity` and implements `IEntityInt` (from AyCode.Interfaces). Used for domain-specific entities and complex DTOs.
|
|
6. **Two DTO base strategies exist:**
|
|
- `ModelDtoBase<TMainEntity>` — for simple DTOs (e.g. `CustomerDto`). Manual `CopyEntityValuesToDto`/`CopyDtoValuesToEntity` overrides. Uses `Activator.CreateInstance<T>()` in `CreateMainEntity()`.
|
|
- `MgEntityBase` + `IModelDtoBase<T>` — for complex DTOs with LinqToDB `[Association]` navigations (e.g. `MgOrderDto`, `MgOrderItemDto`). Uses `PropertyHelper.CopyPublicValueTypeProperties()` for automatic value-type copy.
|
|
7. **`GenericAttribute`** = polymorphic key-value store. `KeyGroup` = owner type name, `EntityId` = owner ID, `Key` = attribute name, `Value` = string value. Use `GenericAttributeExtensions.GetValueOrNull<T>()`/`GetValueOrDefault<T>()`/`TryGetValue<T>()` — never parse raw strings manually.
|
|
|
|
## Data Access Patterns
|
|
8. **`MgDbTableBase<TEntity>`** = repository base wrapping nopCommerce `EntityRepository<TEntity>`. Adds `GetAll()` (`IQueryable<T>`), automatic timestamp handling (`ITimeStampCreated`/`ITimeStampModified`), virtual CRUD hooks (`OnInsert`/`OnUpdate`/`OnDelete`).
|
|
9. **`MgDtoDbTableBase<TDtoEntity, TMainEntity>`** = DTO-aware repository. **CRITICAL: All Delete methods throw — always use `DeleteMainEntityById(int id)`.** Event bridging: DTO insert/update events → main entity events.
|
|
10. **`MgDbContextBase`** = DB context base (NOT EF Core DbContext — wraps `INopDataProvider` and `IRepository<T>` nopCommerce repos). Provides `Transaction`/`TransactionSafe`/`TransactionAsync`/`TransactionSafeAsync`. TransactionSafe variants use global `SemaphoreSlim` lock for serialized access.
|
|
|
|
## Service Patterns
|
|
11. **`MgBackgroundServiceBase`** — inherits `Microsoft.Extensions.Hosting.BackgroundService`. Loop: `Task.Delay(interval)` → `OnExecuteAsync()`. Pause support. Per-iteration exception handling. **Uses nopCommerce `Nop.Services.Logging.ILogger`** (not Mango logger).
|
|
12. **`MgEventConsumerBase`** — subscribes to `EntityUpdatedEvent<Product>`, `EntityInsertedEvent<Product>`, `CustomerRegisteredEvent`, `OrderPlacedEvent`, `PageRenderingEvent`, `ProductSearchEvent`. Override relevant handlers. Built-in: `CheckAndUpdateProductManageInventoryMethodToManageStock()`.
|
|
13. **`NopLogWriter`** — AyCode → nopCommerce log bridge. Log level mapping: `Detail/Trace/Debug/Info` → `Information`; `Suggest/Warning` → `Warning`; `Error` → `Error`. Uses `TransactionScope(Suppress)` to avoid nesting.
|
|
|
|
## Conventions
|
|
14. **`Mg` prefix** for all custom types: `MgEntityBase`, `MgOrderDto`, `MgDbTableBase`, etc.
|
|
15. **No redundant code** — before writing new logic, check whether similar methods already exist in the current context. Reuse or extract shared logic.
|
|
16. **Keep all .md files in sync** — when you modify code and you know which .md file documents it, update that .md file too. If you notice a contradiction between code and an .md file, automatically update the .md to match the code (code is the source of truth). When fixing a reference, check other .md files that may share the same broken reference. If the root cause is at a lower layer, fix it there first. During code review, if you find useful behavior or conventions not yet documented, briefly suggest what to document and where — but do not add new content without approval.
|
|
17. All AyCode references are via **DLL** (not ProjectReference) — this is intentional. Types not defined in this library (e.g. `IEntityInt`, `IId<T>`, `AcConst`, `ToonDescription`) likely live in AyCode.Core. DLL HintPaths in .csproj point to the correct relative location.
|
|
18. **Documentation layering** — write `.md` documentation at the **defining layer** (where the code lives). Higher-layer `.md` files reference AyCode.Core base docs using the form `AyCode.Core/{Project}/docs/FILENAME.md` (resolved via rule 17 base path). Document only project-specific overrides or extensions. Never duplicate base-layer descriptions in consumer-level docs.
|
|
19. **LinqToDB associations** — use `[Association(ThisKey = nameof(FK), OtherKey = nameof(Target.Id), CanBeNull = true/false)]` for navigation properties in DTOs.
|
|
20. **Timestamp auto-management** — entities with `ITimeStampCreated` or `ITimeStampModified` get automatic UTC timestamps in `MgDbTableBase` CRUD hooks. Don't set these manually.
|
|
|
|
## Reference Modes
|
|
- **Full stack** (ProjectReference, all 3 libraries) — for nopCommerce plugins needing entity access, data layer, and services.
|
|
- **Types only** (DLL reference, `Mango.Nop.Core` only) — for projects that only need DTOs, entities, and interfaces without the nopCommerce runtime dependency.
|