Compare commits
No commits in common. "1b11ca257957c661a590f833de67711032c4499c" and "1a9e0dcf0b207c5f3ffa60780c9b9e856cf31cbc" have entirely different histories.
1b11ca2579
...
1a9e0dcf0b
File diff suppressed because one or more lines are too long
17
CLAUDE.md
17
CLAUDE.md
|
|
@ -1,17 +0,0 @@
|
|||
CRITICAL: Your FIRST action in every session MUST be reading `.github/copilot-instructions.md`. Execute ALL session-start instructions found there before responding to any user query. It is the single source of truth for this repo.
|
||||
|
||||
## SEQUENTIAL EXECUTION OVERRIDE
|
||||
The AI AGENT CORE PROTOCOL in copilot-instructions.md requires STRICT SEQUENTIAL execution. This OVERRIDES your default parallelization behavior. Do NOT parallelize doc reads with code searches. The sequence is:
|
||||
1. Read copilot-instructions.md → process its rules FULLY
|
||||
2. Read ALL docs/ .md files listed in the protocol → wait for completion
|
||||
3. Output [LOADED_DOCS: ...] prefix
|
||||
4. ONLY THEN respond to the user's query or search code
|
||||
|
||||
## Tool mapping for AI AGENT CORE PROTOCOL
|
||||
The copilot-instructions.md references Copilot tool names. Map them to Claude Code tools:
|
||||
- `get_file` / `file_search` → `Read`, `Glob`, `Grep`
|
||||
- `code_search` / `get_symbols_by_name` / `find_symbol` → `Grep`, `Glob`
|
||||
- `replace_string_in_file` / `edit_file` → `Edit`
|
||||
- `create_file` → `Write`
|
||||
|
||||
Follow the protocol using YOUR tools. The rules (LOADED_DOCS prefix, hard-gate, no-re-read, context recovery, explicit consent) apply equally to Claude Code.
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
|||
namespace Mango.Nop.Core { public static class AcBinaryForcedInit { public static void ForceRegister() { System.Console.WriteLine("[SGEN TESTING] AcBinaryForcedInit called."); AyCode.Core.Serializers.Generated.AcBinaryGeneratedWritersInit.Register(); } } }
|
||||
|
|
@ -6,7 +6,7 @@ using Nop.Core.Domain.Customers;
|
|||
|
||||
namespace Mango.Nop.Core.Dtos;
|
||||
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
[LinqToDB.Mapping.Table(Name = nameof(Customer))]
|
||||
[System.ComponentModel.DataAnnotations.Schema.Table(nameof(Customer))]
|
||||
[ToonDescription($"Data transfer object for {nameof(Customer)}", TypeRelation = ToonTypeRelation.DtoOf, RelatedTypes = [typeof(Customer)])]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<BaseOutputPath>bin\FruitBank</BaseOutputPath>
|
||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<CopyRefAssembliesToPublishDirectory>true</CopyRefAssembliesToPublishDirectory>
|
||||
</PropertyGroup>
|
||||
|
|
@ -41,20 +40,9 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Core.Serializers.SourceGenerator\AyCode.Core.Serializers.SourceGenerator.csproj"
|
||||
OutputItemType="Analyzer"
|
||||
ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="ExtendedFactories\" />
|
||||
<Folder Include="ExtendedModels\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="docs\**\*.md" />
|
||||
<None Include="**\README.md" Exclude="$(DefaultItemExcludes);docs\**" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Nop.Core.Domain.Customers;
|
|||
/// <summary>
|
||||
/// Represents a customer
|
||||
/// </summary>
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
[ToonDescription("NopCommerce customer entity")]
|
||||
public partial class Customer : BaseEntity, ISoftDeletedEntity
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Nop.Core.Domain.Customers;
|
|||
/// <summary>
|
||||
/// Represents a customer role
|
||||
/// </summary>
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
public partial class CustomerRole : BaseEntity
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ namespace Nop.Core.Domain.Discounts;
|
|||
/// <summary>
|
||||
/// Represents a discount-product mapping class
|
||||
/// </summary>
|
||||
// SGen incompatible: DiscountMapping.Id is readonly (new int Id { get; }) — generated reader cannot set it (CS0200)
|
||||
//[AcBinarySerializable(false, true, false, true, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
public partial class DiscountProductMapping : DiscountMapping
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Nop.Core.Domain.Common;
|
|||
/// <summary>
|
||||
/// Represents a generic attribute
|
||||
/// </summary>
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
[ToonDescription("NopCommerce generic attribute for key-value storage", Purpose = "A flexible key-value store used to extend entities with custom business logic data without changing the database schema")]
|
||||
public partial class GenericAttribute : BaseEntity
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace Nop.Core.Domain.Orders;
|
|||
/// <summary>
|
||||
/// Represents an order
|
||||
/// </summary>
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
[ToonDescription("NopCommerce order entity with payment and shipping")]
|
||||
public partial class Order : BaseEntity, ISoftDeletedEntity
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ using AyCode.Core.Serializers.Toons;
|
|||
/// <summary>
|
||||
/// Represents an order item
|
||||
/// </summary>
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
[ToonDescription("NopCommerce order item entity")]
|
||||
public partial class OrderItem : BaseEntity
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Nop.Core.Domain.Orders;
|
|||
/// <summary>
|
||||
/// Represents an order note
|
||||
/// </summary>
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
[ToonDescription("NopCommerce order note entity")]
|
||||
public partial class OrderNote : BaseEntity
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Nop.Core.Domain.Catalog;
|
|||
/// <summary>
|
||||
/// Represents a product
|
||||
/// </summary>
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
[ToonDescription("Core nopCommerce product entity with catalog, pricing, and inventory management")]
|
||||
public partial class Product : BaseEntity, ILocalizedEntity, ISlugSupported, IAclSupported, IStoreMappingSupported, IDiscountSupported<DiscountProductMapping>, ISoftDeletedEntity
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public interface IMgStockQuantityHistory
|
|||
/// <summary>
|
||||
/// Represents a stock quantity change entry
|
||||
/// </summary>
|
||||
[AcBinarySerializable(false, true, false, true, false, false)]
|
||||
[AcBinarySerializable(false, true, false, true)]
|
||||
[Table(Name = nameof(StockQuantityHistory))]
|
||||
[ToonDescription("NopCommerce stock movement log", Purpose = "Audit trail for physical and logical stock movements")]
|
||||
public partial class StockQuantityHistory : BaseEntity, IMgStockQuantityHistory
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
# Mango.Nop.Core
|
||||
|
||||
@project {
|
||||
type = "framework"
|
||||
own-dep-projects = [
|
||||
"AyCode.Core, AyCode.Core.Server, AyCode.Entities, AyCode.Entities.Server, AyCode.Interfaces, AyCode.Interfaces.Server, AyCode.Utils (in AyCode.Core repo)"
|
||||
]
|
||||
}
|
||||
|
||||
Shared domain library containing entities, DTOs, interfaces, and nopCommerce entity mirrors. **net9.0**. Zero nopCommerce runtime dependency.
|
||||
|
||||
## Documentation
|
||||
|
||||
| Document | Topic |
|
||||
|---|---|
|
||||
| `DTOS.md` | DTO system — two mapping strategies, all DTO types, GenericAttribute typed access |
|
||||
| `NOP_DEPENDENCIES.md` | NopDependencies pattern — mirror copies, namespace rules, file list |
|
||||
|
||||
## Folder Structure
|
||||
|
||||
| Folder | Purpose |
|
||||
|---|---|
|
||||
| `Dtos/` | DTO classes shared across consumers |
|
||||
| `Entities/` | Custom domain entities |
|
||||
| `Extensions/` | Extension methods for `BaseEntity` collections and `GenericAttribute` |
|
||||
| `Interfaces/` | DTO interfaces, soft-delete, foreign key markers |
|
||||
| `Loggers/` | `ILogger` / `Logger` — logging abstraction wrapping AyCode logger |
|
||||
| `Models/` | Login request/response models |
|
||||
| `NopDependencies/` | Mirror copies of nopCommerce entity classes (same namespaces as originals) |
|
||||
| `Services/` | `IMgLockService` interface |
|
||||
| `Utils/` | `CommonHelper2` — email validation, type conversion utilities |
|
||||
|
||||
## Entity Hierarchy
|
||||
|
||||
```
|
||||
Nop.Core.BaseEntity (NopDependencies/, implements IBaseEntity)
|
||||
+-- MgEntityBase (Entities/, implements IEntityInt from AyCode)
|
||||
+-- MgOrderDto<TOrderItemDto, TProductDto>
|
||||
+-- MgOrderItemDto<TProductDto>
|
||||
+-- MgProductDto
|
||||
+-- MgStockQuantityHistoryDto<TProductDto>
|
||||
+-- MgStockTaking<TStockTakingItem>
|
||||
+-- MgStockTakingItem<TStockTaking, TProduct>
|
||||
```
|
||||
|
||||
## Key Types (not in docs/)
|
||||
|
||||
### Entities
|
||||
|
||||
| Type | Key features |
|
||||
|---|---|
|
||||
| `MgEntityBase` | Inherits `BaseEntity`, implements `IEntityInt`. `ToString()` -> `"{TypeName}; Id: {Id}"` |
|
||||
| `MgStockTaking<TStockTakingItem>` | `StartDateTime`, `IsClosed`, `List<TStockTakingItem>` navigation. Implements `ITimeStampInfo` |
|
||||
| `MgStockTakingItem<TStockTaking, TProduct>` | `StockTakingId`, `ProductId`, `IsMeasured`, stock quantities. Navigations to parent and product |
|
||||
|
||||
### Extensions
|
||||
|
||||
| Method | Purpose |
|
||||
|---|---|
|
||||
| `UpdateBaseEntityCollection` | Add/update/remove entities in a list by Id match |
|
||||
|
||||
### Loggers
|
||||
|
||||
Extends AyCode logging infrastructure — for base types see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md`.
|
||||
|
||||
| Type | Inherits | Purpose |
|
||||
|---|---|---|
|
||||
| `ILogger` | `IAcLoggerBase` | Mango-level logger interface |
|
||||
| `ILogger<TCategory>` | `ILogger` | Generic category logger interface |
|
||||
| `Logger` | `AcLoggerBase` | Logger implementation with `IAcLogWriterBase[]` writers |
|
||||
| `Logger<TCategory>` | `Logger` | Typed logger — category name from `typeof(TCategory).Name` |
|
||||
|
||||
### Models
|
||||
|
||||
| Type | Purpose |
|
||||
|---|---|
|
||||
| `MgLoginModelRequest` | `Email` + `Password` for SignalR/API login |
|
||||
| `MgLoginModelResponse` | `CustomerDto?` + `ErrorMessage`. Computed `IsSuccesLogin` |
|
||||
|
||||
### Other
|
||||
|
||||
| Type | Purpose |
|
||||
|---|---|
|
||||
| `NopCommonConst` | Abstract const class inheriting `AcConst` (placeholder) |
|
||||
| `CommonHelper2` | Email validation, IP validation, type conversion (`To<T>`), string utilities |
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `linq2db` — data access, `[Association]` / `[Table]` attributes
|
||||
- `Microsoft.AspNetCore.Mvc.NewtonsoftJson` — JSON serialization
|
||||
- Binary serialization: `AcBinarySerializer` (see `AyCode.Core/AyCode.Core/docs/BINARY/BINARY_FORMAT.md`). SignalR transport: `AcSignalR` (see `AyCode.Core/AyCode.Services/docs/SIGNALR/README.md`).
|
||||
- `AyCode.Core.Serializers.SourceGenerator` (ProjectReference, `OutputItemType="Analyzer"`) — compile-time binary serializer. See [`AyCode.Core/docs/BINARY_SOURCE_GEN.md`](../../../../../../Aycode/Source/AyCode.Core/AyCode.Core/docs/BINARY_SOURCE_GEN.md)
|
||||
- AyCode DLL references: `AyCode.Interfaces`, `AyCode.Core`, `AyCode.Utils`, `AyCode.Entities` (types only, no runtime nopCommerce dependency)
|
||||
|
||||
## AcBinary Source Generator (SGen)
|
||||
|
||||
9 types annotated with `[AcBinarySerializable]`. For general SGen docs see [`AyCode.Core/docs/BINARY_SOURCE_GEN.md`](../../../../../../Aycode/Source/AyCode.Core/AyCode.Core/docs/BINARY_SOURCE_GEN.md).
|
||||
|
||||
Requires `InternalsVisibleTo("Mango.Nop.Core")` in `AyCode.Core/Properties/AssemblyInfo.cs`.
|
||||
|
||||
### Excluded types
|
||||
|
||||
| Type | Reason |
|
||||
|---|---|
|
||||
| `DiscountProductMapping` | Base `DiscountMapping` hides `BaseEntity.Id` with readonly `new int Id { get; }` → CS0200. Uses compiled-expression fallback. |
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# Architecture
|
||||
|
||||
## Framework vs. Consumer Boundary
|
||||
|
||||
This solution is **Layer 2 — Domain framework** (NopCommerce-plugin base). Built on Layer 0 (AyCode.Core), consumed by Layer 3 (specific plugin apps, plural and unknown). Full doctrine: AyCode.Core's `docs/ARCHITECTURE.md#framework-vs-consumer-boundary`.
|
||||
|
||||
### Layer position
|
||||
|
||||
```
|
||||
Layer 0 — AyCode.Core universal primitives (serializers, logging, entities)
|
||||
Layer 2 — Mango.Nop.Core this solution — NopCommerce-plugin domain framework
|
||||
Layer 3 — Consumer plugin apps specific plugin projects with business logic
|
||||
```
|
||||
|
||||
### Nop-plugin-framework-specific notes
|
||||
|
||||
- **`NopDependencies/`** mirrors NopCommerce entity classes under the original Nop namespaces — no runtime Nop dependency, compile-time type parity only
|
||||
- **DTOs** use type parameters for consumer entity types (e.g. `MgOrderDto<TOrderItemDto, TProductDto>`) — concrete types are provided by plugin projects
|
||||
- **Entity hierarchy**: `Nop.Core.BaseEntity` (mirrored) → `MgEntityBase` → generic DTOs/entities parameterized for consumers
|
||||
- **`Logger` / `ILogger`** extend AyCode logging (`AcLoggerBase`) — plugin projects may subclass again if business-specific writers are needed
|
||||
- **Zero runtime Nop dependency** — plugin apps bring their own Nop runtime
|
||||
|
||||
### What belongs here vs. in a plugin
|
||||
|
||||
**Yes, framework:**
|
||||
- NopCommerce entity mirrors (for cross-plugin type sharing)
|
||||
- Generic DTOs with type parameters
|
||||
- Shared interfaces and extensions for NopCommerce domain entities
|
||||
- Logger base with AyCode integration
|
||||
|
||||
**No, plugin only:**
|
||||
- Plugin-specific business logic
|
||||
- Plugin-named types (`XxxPlugin`, `XxxService` where Xxx is a specific product)
|
||||
- Hardcoded plugin configuration, tenant, or product IDs
|
||||
|
||||
## Related Documents
|
||||
|
||||
| Topic | Document |
|
||||
|---|---|
|
||||
| Framework-first doctrine (full) | `../../../../../../../Aycode/Source/AyCode.Core/docs/ARCHITECTURE.md#framework-vs-consumer-boundary` |
|
||||
| Placement rules, anti-patterns | `CONVENTIONS.md#framework-first-placement` |
|
||||
| DTO system and GenericAttribute typed access | `DTOS.md` |
|
||||
| NopDependencies mirror pattern | `NOP_DEPENDENCIES.md` |
|
||||
| Folder structure and key types index | `../README.md` |
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
# Conventions
|
||||
|
||||
For core framework conventions (Ac prefix, naming patterns, Session/Transaction, etc.) see AyCode.Core's `docs/CONVENTIONS.md`.
|
||||
|
||||
## Framework-First Placement
|
||||
|
||||
Follow the doctrine in AyCode.Core's `docs/CONVENTIONS.md#framework-first-placement`. Same verdict table and hard rules apply.
|
||||
|
||||
**Nop-plugin-framework-specific additions:**
|
||||
- `NopDependencies/` mirror classes stay in their original Nop namespaces — don't rename, don't add plugin-specific fields
|
||||
- DTOs parameterize via type arguments, not concrete plugin types
|
||||
- Any plugin-specific business logic belongs in the plugin project, not here
|
||||
- Adding a new shared DTO: ensure it is useful for 2+ plugin projects (otherwise keep in the single plugin)
|
||||
|
||||
## Naming
|
||||
|
||||
- **`Mg` prefix**: for Mango-framework-level types (e.g. `MgEntityBase`, `MgOrderDto`, `MgProductDto`)
|
||||
- **`IMg` prefix**: for Mango-framework-level interfaces (e.g. `IMgModelDtoBase`, `IMgSoftRemoveEntity`)
|
||||
- **No prefix**: for NopCommerce entity mirrors in `NopDependencies/` — they stay in Nop namespace, same name as upstream
|
||||
|
||||
## XML Documentation
|
||||
|
||||
`<summary>` — brief, developer-facing, readable in VS IntelliSense tooltip. NO implementation details, NO wire-format / byte-level / perf specifics — those live in `docs/TOPIC/*.md`. Add `<example>` only when usage is non-obvious; otherwise omit.
|
||||
|
||||
## See Also
|
||||
|
||||
- Core framework naming (`Ac` / `IAc` prefixes), patterns, serialization conventions: AyCode.Core's `docs/CONVENTIONS.md`
|
||||
- Framework-first verdict table (full): AyCode.Core's `docs/CONVENTIONS.md#framework-first-placement`
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
# DTO System
|
||||
|
||||
> Part of `Mango.Nop.Core`. See `Mango.Nop.Core/README.md` for project overview.
|
||||
|
||||
## Two Mapping Strategies
|
||||
|
||||
### Strategy 1: `ModelDtoBase<T>` (simple DTOs)
|
||||
|
||||
Used by: `CustomerDto`, `MgGenericAttributeDto`
|
||||
|
||||
```
|
||||
ModelDtoBase → ModelDtoBase<Customer> → CustomerDto
|
||||
```
|
||||
|
||||
- Manual `CopyEntityValuesToDto`/`CopyDtoValuesToEntity` overrides
|
||||
- `CreateMainEntity()` uses `Activator.CreateInstance<T>()`
|
||||
- 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 value-type 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
|
||||
|
||||
## DTO Types
|
||||
|
||||
| Type | Generic params | Maps to entity | Key features |
|
||||
|---|---|---|---|
|
||||
| `ModelDtoBase` | — | — | Abstract base, `int Id` only |
|
||||
| `ModelDtoBase<TMainEntity>` | `TMainEntity : BaseEntity` | `TMainEntity` | `CreateMainEntity()`, `CopyEntityValuesToDto()`, `CopyDtoValuesToEntity()` |
|
||||
| `MgOrderDto<TOrderItemDto, TProductDto>` | `TOrderItemDto : IMgOrderItemDto<TProductDto>`, `TProductDto : IMgProductDto` | `Order` | Has `Customer`, `List<TOrderItemDto>`, `List<OrderNote>` navigations. Enum wrappers: `OrderStatus`, `ShippingStatus`, `PaymentStatus` |
|
||||
| `MgOrderItemDto<TProductDto>` | `TProductDto : IMgProductDto` | `OrderItem` | Has `TProductDto?` navigation. Computed `ProductName` property |
|
||||
| `MgProductDto` | — | *(commented out)* | Base product DTO. Name, Price, StockQuantity, dimensions. No entity mapping methods (currently commented out) |
|
||||
| `MgGenericAttributeDto` | — | `GenericAttribute` | Inherits `GenericAttribute` directly (not `ModelDtoBase`). Full bidirectional mapping |
|
||||
| `MgStockQuantityHistoryDto<TProductDto>` | `TProductDto : IMgProductDto` | `StockQuantityHistory` | Has `TProductDto` navigation. Mapping methods `NotImplementedException` (stub) |
|
||||
| `CustomerDto` | — | `Customer` | `Username`, `Email`, `FirstName`, `LastName`, `FullName` computed. Uses `[AcBinarySerializable]` and LinqToDB `[Table]` |
|
||||
|
||||
## DTO Interfaces
|
||||
|
||||
| Interface | Extends | Purpose |
|
||||
|---|---|---|
|
||||
| `IModelDtoBase` | `IEntityInt`, `IModelDtoBaseEmpty` | Marker for all DTOs with `int Id` |
|
||||
| `IModelDtoBase<TMainEntity>` | `IModelDtoBase` | Bidirectional mapping contract: `CreateMainEntity()`, `CopyDtoValuesToEntity()`, `CopyEntityValuesToDto()` |
|
||||
| `IMgOrderDto<TOrderItemDto, TProductDto>` | `IEntityInt`, `ISoftDeletedEntity` | Order DTO contract with navigation properties and initialization methods |
|
||||
| `IMgOrderItemDto<TProductDto>` | `IEntityInt` | Order item DTO contract with product navigation |
|
||||
| `IMgProductDto` | `IEntityInt`, `ILocalizedEntity`, `ISlugSupported`, `IAclSupported`, `IStoreMappingSupported`, `ISoftDeletedEntity` | Product DTO contract |
|
||||
|
||||
## GenericAttribute Typed Access
|
||||
|
||||
`GenericAttributeExtensions` provides typed access to nopCommerce's polymorphic key-value store:
|
||||
|
||||
| Method | Signature | Purpose |
|
||||
|---|---|---|
|
||||
| `GetValueOrNull<TValue>` | `(IEnumerable<GenericAttribute>, string key) -> TValue?` | Get typed value, returns null if not found |
|
||||
| `GetValueOrDefault<TValue>` | `(IEnumerable<GenericAttribute>, string key, TValue default) -> TValue` | Same with default fallback |
|
||||
| `TryGetValue<TValue>` | `(IEnumerable<GenericAttribute>, string key, out TValue?) -> bool` | Try-pattern for GA value |
|
||||
| `AddNewGenericAttribute` | `(ICollection<GenericAttribute>, ...) -> GenericAttribute` | Create and add new GA with UTC timestamp |
|
||||
|
||||
**Rule:** Always use these extension methods — never parse `GenericAttribute.Value` strings manually.
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# NopDependencies Pattern
|
||||
|
||||
> Part of `Mango.Nop.Core`. See `Mango.Nop.Core/README.md` for project overview.
|
||||
|
||||
## Why
|
||||
|
||||
`Mango.Nop.Core` has **zero nopCommerce runtime dependency**. This allows it to be referenced by projects that don't have the full nopCommerce stack (e.g. Blazor/MAUI clients that only need DTOs and interfaces).
|
||||
|
||||
To achieve this, `NopDependencies/` contains **mirror copies** of nopCommerce entity classes with the **same namespace** as the originals:
|
||||
|
||||
```csharp
|
||||
// In NopDependencies/BaseEntity.cs — same namespace as nopCommerce
|
||||
namespace Nop.Core;
|
||||
public abstract partial class BaseEntity : IBaseEntity
|
||||
{
|
||||
public int Id { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
At compile time, projects referencing only `Mango.Nop.Core` get these mirror types. Projects with the full nopCommerce stack get the real types — they are type-compatible because they share the same namespace and shape.
|
||||
|
||||
## Rules
|
||||
|
||||
- **DO NOT modify** files in `NopDependencies/` unless the nopCommerce version changes
|
||||
- **DO NOT change namespaces** — they must match the original nopCommerce types exactly
|
||||
- All mirror classes are `partial` — they can be extended but should not be modified directly
|
||||
|
||||
## File List
|
||||
|
||||
| File | Namespace | Type |
|
||||
|---|---|---|
|
||||
| `BaseEntity.cs` | `Nop.Core` | `BaseEntity` (abstract, `IBaseEntity`) + `IBaseEntity` interface |
|
||||
| `Catalogs/Customer.cs` | `Nop.Core.Domain.Customers` | `Customer` |
|
||||
| `Catalogs/CustomerRole.cs` | `Nop.Core.Domain.Customers` | `CustomerRole` |
|
||||
| `Catalogs/Order.cs` | `Nop.Core.Domain.Orders` | `Order` |
|
||||
| `Catalogs/OrderItem.cs` | `Nop.Core.Domain.Orders` | `OrderItem` |
|
||||
| `Catalogs/OrderNote.cs` | `Nop.Core.Domain.Orders` | `OrderNote` |
|
||||
| `Catalogs/Product.cs` | `Nop.Core.Domain.Catalog` | `Product` |
|
||||
| `Catalogs/GenericAttribute.cs` | `Nop.Core.Domain.Common` | `GenericAttribute` |
|
||||
| `Catalogs/StockQuantityHistory.cs` | `Nop.Core.Domain.Catalog` | `StockQuantityHistory` |
|
||||
| `Catalogs/DiscountMapping.cs` | `Nop.Core.Domain.Catalog` | `DiscountMapping` |
|
||||
| `Catalogs/DiscountProductMapping.cs` | `Nop.Core.Domain.Catalog` | `DiscountProductMapping` |
|
||||
|
||||
**Enums:** `OrderStatus`, `PaymentStatus`, `ShippingStatus`, `ProductType`, `ManageInventoryMethod`, `BackorderMode`, `LowStockActivity`, `GiftCardType`, `RentalPricePeriod`, `RecurringProductCyclePeriod`, `DownloadActivationType`, `TaxDisplayType`, `VatNumberStatus`
|
||||
|
||||
**Interfaces:** `ISoftDeletedEntity`, `ILocalizedEntity`, `ISlugSupported`, `IAclSupported`, `IStoreMappingSupported`, `IDiscountSupported`
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# Mango.Nop.Core documentation
|
||||
|
||||
Topic documentation for the `Mango.Nop.Core` project (Layer 2 framework — NopCommerce-adjacent base types).
|
||||
|
||||
## Reference docs (flat)
|
||||
|
||||
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — Project architecture
|
||||
- [`CONVENTIONS.md`](CONVENTIONS.md) — Project-specific conventions
|
||||
- [`DTOS.md`](DTOS.md) — DTO system, mapping strategies
|
||||
- [`NOP_DEPENDENCIES.md`](NOP_DEPENDENCIES.md) — NopCommerce entity mirror pattern
|
||||
|
||||
## Navigation
|
||||
|
||||
Per the AI Agent Core Protocol (folder navigation rule), start from this README when browsing `docs/`. All docs at this level are single-file reference; topic folders (e.g., LOGGING/) exist only at sub-projects that host a variant (see `../Mango.Nop.Services/docs/LOGGING/`).
|
||||
|
||||
## See also
|
||||
|
||||
- **Repo-level conventions**: `../../docs/CONVENTIONS.md`
|
||||
- **Base framework**: `../../../../../Aycode/Source/AyCode.Core/` docs
|
||||
|
|
@ -44,10 +44,4 @@
|
|||
<HintPath>..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\$(Configuration)\net9.0\AyCode.Utils.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="docs\**\*.md" />
|
||||
<None Include="**\README.md" Exclude="$(DefaultItemExcludes);docs\**" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
# Mango.Nop.Data
|
||||
|
||||
@project {
|
||||
type = "framework"
|
||||
own-dep-projects = [
|
||||
"AyCode.Core, AyCode.Core.Server, AyCode.Entities, AyCode.Entities.Server, AyCode.Interfaces, AyCode.Interfaces.Server, AyCode.Utils (in AyCode.Core repo)"
|
||||
]
|
||||
}
|
||||
|
||||
Data access layer with repository base classes and DB context abstractions. **net9.0**.
|
||||
|
||||
## Documentation
|
||||
|
||||
| Document | Topic |
|
||||
|---|---|
|
||||
| `REPOSITORIES.md` | MgDbTableBase, MgDtoDbTableBase — CRUD hooks, timestamps, delete rules, event bridging |
|
||||
| `TRANSACTIONS.md` | MgDbContextBase — 4 transaction methods, lock strategy, callback contract |
|
||||
|
||||
## Folder Structure
|
||||
|
||||
| Folder | Purpose |
|
||||
|---|---|
|
||||
| `Interfaces/` | Repository interfaces: `IMgDalBase`, `IMgDbContextBase`, `IMgDbTableBase` |
|
||||
| `Repositories/` | Repository base implementations: `MgDalBase`, `MgDbContextBase`, `MgDbTableBase`, `MgDtoDbTableBase` |
|
||||
|
||||
## Inheritance Chains
|
||||
|
||||
### Repository hierarchy
|
||||
```
|
||||
nopCommerce EntityRepository<TEntity> (Nop.Data)
|
||||
+-- MgDbTableBase<TEntity>
|
||||
+-- MgDtoDbTableBase<TDtoEntity, TMainEntity>
|
||||
```
|
||||
|
||||
### Context hierarchy
|
||||
```
|
||||
MgDbContextBase (abstract, implements IMgDbContextBase)
|
||||
+-- [Consumer DbContexts in plugins]
|
||||
```
|
||||
|
||||
### DAL hierarchy
|
||||
```
|
||||
MgDalBase<TDbContext> (implements IMgDalBase<TDbContext>)
|
||||
+-- [Consumer DALs in plugins]
|
||||
```
|
||||
|
||||
## Interfaces
|
||||
|
||||
| Interface | Purpose |
|
||||
|---|---|
|
||||
| `IMgDbTableBase` | Marker interface for repository classes |
|
||||
| `IMgDbContextBase` | Contract: `Logger`, `DataProvider`, `Orders`, `Products`, 4 transaction methods |
|
||||
| `IMgDalBase` | `Name` property |
|
||||
| `IMgDalBase<TDbContext>` | `Context`, `MutextLock` — typed access to DB context |
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `Mango.Nop.Core` (ProjectReference)
|
||||
- `Nop.Core`, `Nop.Data` (nopCommerce ProjectReferences)
|
||||
- `Microsoft.AspNetCore.Mvc.NewtonsoftJson`
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
# Mango.Nop.Data documentation
|
||||
|
||||
Topic documentation for the `Mango.Nop.Data` project (Layer 2, data access layer).
|
||||
|
||||
## Reference docs (flat)
|
||||
|
||||
- [`REPOSITORIES.md`](REPOSITORIES.md) — Repository pattern usage
|
||||
- [`TRANSACTIONS.md`](TRANSACTIONS.md) — Transaction pattern usage
|
||||
|
||||
## Navigation
|
||||
|
||||
Per the AI Agent Core Protocol (folder navigation rule), start from this README when browsing `docs/`. All docs at this level are single-file reference.
|
||||
|
||||
## See also
|
||||
|
||||
- **Repo-level conventions**: `../../docs/CONVENTIONS.md`
|
||||
- **Core DTOs**: `../Mango.Nop.Core/docs/DTOS.md`
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# Repository Pattern
|
||||
|
||||
> Part of `Mango.Nop.Data`. See `Mango.Nop.Data/README.md` for project overview.
|
||||
> For transaction patterns see `docs/TRANSACTIONS.md`.
|
||||
|
||||
## MgDbTableBase\<TEntity\>
|
||||
|
||||
Repository base wrapping nopCommerce `EntityRepository<TEntity>`.
|
||||
|
||||
**Constructor:**
|
||||
```csharp
|
||||
MgDbTableBase(IEventPublisher, INopDataProvider, IShortTermCacheManager, IStaticCacheManager, AppSettings)
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
| Feature | Detail |
|
||||
|---|---|
|
||||
| `GetAll()` | Returns `IQueryable<TEntity>` from `Table` property |
|
||||
| Automatic timestamps | `ITimeStampCreated.Created` set on insert; `ITimeStampModified.Modified` set on insert/update |
|
||||
| CRUD hooks | `OnInsert(entity)`, `OnUpdate(entity)`, `OnDelete(entity)` — virtual, overridable |
|
||||
| Cache clear | `OnUpdate` clears `IStaticCacheManager` (currently clears all — TODO noted in code) |
|
||||
| All CRUD overrides | Overrides all sync/async `Insert`, `Update`, `Delete` methods to call hooks before `base.*` |
|
||||
| `DeleteAsync(int entityId)` | Convenience: load by id then delete |
|
||||
| `DeleteAsync(predicate, bool publishEvent)` | When `publishEvent=true`, loads entities first then deletes with events |
|
||||
|
||||
## MgDtoDbTableBase\<TDtoEntity, TMainEntity\>
|
||||
|
||||
DTO-aware repository for when the DTO entity (`TDtoEntity`) maps to a different main nopCommerce entity (`TMainEntity`). This is needed because LinqToDB tables are registered for DTOs, but nopCommerce events must fire on the main entity type.
|
||||
|
||||
### Features
|
||||
|
||||
| Feature | Detail |
|
||||
|---|---|
|
||||
| `GetMainEntityById(id)` | Loads `TMainEntity` from `INopDataProvider.GetTable<TMainEntity>()` |
|
||||
| `DeleteMainEntityById(id)` | Deletes the **main entity** (not the DTO) and publishes `EntityDeletedEvent<TMainEntity>` |
|
||||
| Delete overrides | **All Delete methods throw** — forces callers to use `DeleteMainEntityById()` instead |
|
||||
| Event bridging | `EntityInsertedEvent<TDtoEntity>` -> loads main entity -> publishes `EntityInsertedEvent<TMainEntity>` |
|
||||
| Event bridging | `EntityUpdatedEvent<TDtoEntity>` -> loads main entity -> publishes `EntityUpdatedEvent<TMainEntity>` |
|
||||
| Event bridging | `EntityDeletedEvent<TDtoEntity>` -> **throws** (must use `DeleteMainEntityById`) |
|
||||
|
||||
**Critical rule:** Never call `Delete` on a `MgDtoDbTableBase` repository directly. Always use `DeleteMainEntityById(int id)`.
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
# Transaction Pattern
|
||||
|
||||
> Part of `Mango.Nop.Data`. See `Mango.Nop.Data/README.md` for project overview.
|
||||
> For repository base classes see `docs/REPOSITORIES.md`.
|
||||
|
||||
## MgDbContextBase
|
||||
|
||||
Abstract database context base. NOT an EF Core DbContext — wraps `INopDataProvider` and `IRepository<T>` nopCommerce repos.
|
||||
|
||||
**Constructor:**
|
||||
```csharp
|
||||
MgDbContextBase(IRepository<Product>, IRepository<Order>, IRepository<OrderItem>, INopDataProvider, IMgLockService, ILogger)
|
||||
```
|
||||
|
||||
### Standard Repositories
|
||||
|
||||
| Property | Type |
|
||||
|---|---|
|
||||
| `Orders` | `IRepository<Order>` |
|
||||
| `OrderItems` | `IRepository<OrderItem>` |
|
||||
| `Products` | `IRepository<Product>` |
|
||||
| `DataProvider` | `INopDataProvider` (LinqToDB raw queries) |
|
||||
| `Logger` | Mango `ILogger` |
|
||||
| `LockService` | `IMgLockService` (global `SemaphoreSlim`) |
|
||||
|
||||
### 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 (`Complete()`), `false` to rollback.
|
||||
|
||||
**Isolation level:** `ReadCommitted`
|
||||
|
||||
**Error handling:** Catches exceptions, logs, returns `false` (unless `throwException = true`).
|
||||
|
||||
**TransactionSafe variants:** Use `LockService.SemaphoreSlim` for global serialization. Use for order creation, stock adjustment — any operation where concurrent modifications would corrupt data.
|
||||
|
||||
**Async variants:** Run on thread pool via `TaskHelper.ToThreadPoolTask()`.
|
||||
|
||||
## MgDalBase\<TDbContext\>
|
||||
|
||||
Data Access Layer orchestrator. Thin wrapper exposing:
|
||||
|
||||
| Property | Type | Purpose |
|
||||
|---|---|---|
|
||||
| `Name` | `string` | DAL instance name |
|
||||
| `Context` | `TDbContext` | The DB context (typed) |
|
||||
| `MutextLock` | `Mutex` | Cross-process locking |
|
||||
|
|
@ -47,10 +47,4 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="docs\**\*.md" />
|
||||
<None Include="**\README.md" Exclude="$(DefaultItemExcludes);docs\**" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
# Mango.Nop.Services
|
||||
|
||||
@project {
|
||||
type = "framework"
|
||||
own-dep-projects = [
|
||||
"AyCode.Core, AyCode.Core.Server, AyCode.Entities, AyCode.Entities.Server, AyCode.Interfaces, AyCode.Interfaces.Server, AyCode.Utils (in AyCode.Core repo)"
|
||||
]
|
||||
}
|
||||
|
||||
Service base classes for nopCommerce plugin development — background tasks, session management, events, locking, logging. **net9.0**.
|
||||
|
||||
## Documentation
|
||||
|
||||
| Document | Topic |
|
||||
|---|---|
|
||||
| `SERVICES.md` | MgBackgroundServiceBase, MgSessionServiceBase, MgEventConsumerBase, MgLockServiceBase |
|
||||
| `LOGGING/README.md` | NopLogWriter — AyCode-to-nopCommerce log bridge, TransactionScope(Suppress) |
|
||||
|
||||
## Folder Structure
|
||||
|
||||
| Folder | Purpose |
|
||||
|---|---|
|
||||
| `Loggers/` | `NopLogWriter`, `NopLoggerMsSqlNopDataProvider` — AyCode -> nopCommerce log bridge |
|
||||
| *(root)* | `MgBackgroundServiceBase`, `MgSessionServiceBase`, `MgEventConsumerBase`, `MgLockServiceBase`, interfaces |
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `Mango.Nop.Core`, `Mango.Nop.Data` (ProjectReferences)
|
||||
- `Nop.Core`, `Nop.Data`, `Nop.Services`, `Nop.Web.Framework` (nopCommerce ProjectReferences)
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
# NopLogWriter — Logging Bridge
|
||||
|
||||
> Part of `Mango.Nop.Services`. See `Mango.Nop.Services/README.md` for project overview.
|
||||
> For AyCode base logging types (`AcLogItemWriterBase`, `AcLogItem`, log levels) see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md`.
|
||||
|
||||
## Overview
|
||||
|
||||
Bridges AyCode logging to nopCommerce's `Nop.Core.Domain.Logging.Log` table via direct DB insert.
|
||||
|
||||
## NopLogWriter
|
||||
|
||||
| Feature | Detail |
|
||||
|---|---|
|
||||
| Inherits | `AcLogItemWriterBase<AcLogItem>` (AyCode.Core) |
|
||||
| Log level mapping | AyCode `Detail/Trace/Debug/Info` -> nopCommerce `Information`; `Suggest/Warning` -> `Warning`; `Error` -> `Error` |
|
||||
| Direct DB insert | Uses `NopLoggerMsSqlNopDataProvider` with `TransactionScope(Suppress)` to avoid transaction conflicts |
|
||||
|
||||
**Constructor:** `(INopLoggerMsSqlNopDataProvider, CommonSettings, CustomerSettings, IWebHelper, Nop.Services.Logging.ILogger, string? categoryName)`
|
||||
|
||||
## NopLoggerMsSqlNopDataProvider
|
||||
|
||||
Extends `MsSqlNopDataProvider`. Provides isolated DB access for log writes.
|
||||
|
||||
| Method | Purpose |
|
||||
|---|---|
|
||||
| `InsertLogItem<T>()` | Sync insert with own `TransactionScope(Suppress, ReadUncommitted)` |
|
||||
| `InsertLogItemAsync<T>()` | Async insert with own `TransactionScope(Suppress, ReadUncommitted)` |
|
||||
|
||||
The `TransactionScope(Suppress)` is critical — without it, log writes would participate in the caller's transaction, causing nesting conflicts and potential deadlocks.
|
||||
|
||||
## Integration Point
|
||||
|
||||
```
|
||||
Application code -> Mango.Nop.Core.Loggers.ILogger (extends IAcLoggerBase)
|
||||
-> Logger<TCategory> (extends AcLoggerBase, delegates to IAcLogWriterBase[])
|
||||
-> NopLogWriter -> Nop Log table (direct SQL insert)
|
||||
-> [Other AyCode log writers: console, file, SignalR, etc.]
|
||||
```
|
||||
|
||||
**Exception:** `MgBackgroundServiceBase` uses `Nop.Services.Logging.ILogger` directly (nopCommerce logger), not the Mango wrapper.
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
# Mango.Nop.Services documentation
|
||||
|
||||
Topic documentation for the `Mango.Nop.Services` project (Layer 2, service patterns).
|
||||
|
||||
## Reference docs (flat)
|
||||
|
||||
- [`SERVICES.md`](SERVICES.md) — Service pattern usage
|
||||
|
||||
## Topic folders
|
||||
|
||||
- [`LOGGING/`](LOGGING/README.md) — Logger bridge between NopCommerce's logger and AyCode.Core's logger (project-specific variant)
|
||||
|
||||
## Navigation
|
||||
|
||||
Per the AI Agent Core Protocol (folder navigation rule), start from this README when browsing `docs/`. Single-file reference docs remain flat; project-specific variants of framework topics (like LOGGING) live in named subfolders.
|
||||
|
||||
## See also
|
||||
|
||||
- **Base logger** (framework): `../../../../../Aycode/Source/AyCode.Core/AyCode.Core/docs/LOGGING/README.md`
|
||||
- **Remote logger variant**: `../../../../../Aycode/Source/AyCode.Core/AyCode.Services/docs/LOGGING/README.md`
|
||||
- **Server-side logger variant**: `../../../../../Aycode/Source/AyCode.Core/AyCode.Core.Server/docs/LOGGING/README.md`
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
# Service Base Classes
|
||||
|
||||
> Part of `Mango.Nop.Services`. See `Mango.Nop.Services/README.md` for project overview.
|
||||
> For logging bridge see `docs/LOGGING/README.md`.
|
||||
|
||||
## MgBackgroundServiceBase
|
||||
|
||||
Abstract hosted background service. Inherits `Microsoft.Extensions.Hosting.BackgroundService`.
|
||||
|
||||
**Constructor:** `(ILogger, IServiceProvider, int executeIntervalMs)`
|
||||
|
||||
| Feature | Detail |
|
||||
|---|---|
|
||||
| Loop pattern | `ExecuteAsync` loops: `Task.Delay(ExecuteIntervalMs)` -> `OnExecuteAsync()`, with pause support |
|
||||
| `OnExecuteAsync(CancellationToken)` | Abstract — subclass implements the actual work |
|
||||
| `Pause(bool)` | Pauses/resumes the loop without stopping the service |
|
||||
| `ExecuteIntervalMs` | Configurable interval between iterations |
|
||||
| Exception handling | Catches and logs errors per iteration, never crashes the loop |
|
||||
| Logging | Uses nopCommerce `Nop.Services.Logging.ILogger` (**not** `Mango.Nop.Core.Loggers.ILogger`) |
|
||||
|
||||
**Interface:** `IMgBackgroundService : IHostedService, IDisposable`
|
||||
|
||||
## MgSessionServiceBase\<TSessionItem\>
|
||||
|
||||
In-memory session management using `ConcurrentDictionary<string, TSessionItem>`.
|
||||
|
||||
| Method | Signature | Purpose |
|
||||
|---|---|---|
|
||||
| `GetOrCreateSessionItem` | `(string sessionId) -> TSessionItem?` | Get existing or create new via `Activator.CreateInstance` |
|
||||
| `TryAddSessionItem` | `(TSessionItem) -> bool` | Add if not exists, throws if duplicate |
|
||||
| `TryGetSessionItem` | `(string sessionId, out TSessionItem) -> bool` | Try-pattern lookup |
|
||||
| `TryRemoveSessionItem` | `(string sessionId, out TSessionItem) -> bool` | Remove and return |
|
||||
| `TryGetSessionItemBySignlaRConnectionId` | `(string connectionId, out TSessionItem?) -> bool` | Find session by SignalR connection |
|
||||
| `Count` | `() -> int` | Active session count |
|
||||
|
||||
**Interface:** `IMgSessionService<TSessionItem> where TSessionItem : IMgSessionItem`
|
||||
|
||||
## MgSessionItemBase
|
||||
|
||||
Base session item. Primary constructor: `(string sessionKey)`.
|
||||
|
||||
| Property | Type | Purpose |
|
||||
|---|---|---|
|
||||
| `SessionId` | `string` | Unique session identifier |
|
||||
| `SignaRConnectionId` | `string?` | Associated SignalR connection ID |
|
||||
| `RequestCount` | `int` | Request counter |
|
||||
|
||||
**Interface:** `IMgSessionItem` — `SessionId`, `SignaRConnectionId`, `RequestCount`
|
||||
|
||||
## MgEventConsumerBase
|
||||
|
||||
Abstract nopCommerce event consumer. Subscribes to:
|
||||
|
||||
| Event | Handler |
|
||||
|---|---|
|
||||
| `EntityUpdatedEvent<Product>` | `HandleEventAsync(...)` — virtual, empty default |
|
||||
| `EntityInsertedEvent<Product>` | `HandleEventAsync(...)` — virtual, empty default |
|
||||
| `CustomerRegisteredEvent` | `HandleEventAsync(...)` — virtual, empty default |
|
||||
| `OrderPlacedEvent` | `HandleEventAsync(...)` — virtual, empty default |
|
||||
| `PageRenderingEvent` | `HandleEventAsync(...)` — virtual, empty default |
|
||||
| `ProductSearchEvent` | `HandleEventAsync(...)` — virtual, empty default |
|
||||
|
||||
Built-in helper: `CheckAndUpdateProductManageInventoryMethodToManageStock(Product)` — ensures product has `ManageStock` inventory method.
|
||||
|
||||
**Constructor:** `(IMgDbContextBase ctx, IHttpContextAccessor, IEnumerable<IAcLogWriterBase> logWriters)`
|
||||
|
||||
## MgLockServiceBase
|
||||
|
||||
Simple in-process lock using `SemaphoreSlim(1)`. Implements `IMgLockService` (defined in `Mango.Nop.Core.Services`).
|
||||
|
||||
Used by `MgDbContextBase.TransactionSafe*` variants for global serialization.
|
||||
51
README.md
51
README.md
|
|
@ -1,51 +0,0 @@
|
|||
# Mango.Nop Libraries
|
||||
|
||||
> For library domain rules see: `.github/copilot-instructions.md`
|
||||
> For detailed docs see: `docs/`
|
||||
|
||||
Shared nopCommerce extension libraries providing domain entities, DTOs, data access, and service base classes. All target **net9.0** (nopCommerce 4.80.9 requirement).
|
||||
|
||||
## Projects
|
||||
|
||||
| Project | Purpose | Key Types |
|
||||
|---|---|---|
|
||||
| `Mango.Nop.Core` | Domain entities, DTOs, interfaces, nopCommerce entity mirrors (zero nopCommerce runtime dep) | `MgEntityBase`, `ModelDtoBase<T>`, `MgOrderDto<,>`, `MgOrderItemDto<>`, `MgProductDto`, `CustomerDto`, `MgGenericAttributeDto`, `MgStockTaking<>`, `GenericAttributeExtensions` |
|
||||
| `Mango.Nop.Data` | Data access layer — repository base classes, DB context, transactions | `MgDbTableBase<T>`, `MgDtoDbTableBase<,>`, `MgDbContextBase`, `MgDalBase<T>` |
|
||||
| `Mango.Nop.Services` | Service base classes — background services, session, events, locking, logging | `MgBackgroundServiceBase`, `MgSessionServiceBase<T>`, `MgEventConsumerBase`, `MgLockServiceBase`, `NopLogWriter` |
|
||||
|
||||
## Dependency Graph
|
||||
|
||||
See `docs/ARCHITECTURE.md` for full dependency graph, project roles, DTO mapping strategies, and transaction patterns.
|
||||
|
||||
```
|
||||
AyCode.Core (DLL references)
|
||||
↑
|
||||
Mango.Nop.Core (net9.0, zero 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
|
||||
```
|
||||
|
||||
## Reference Modes
|
||||
|
||||
- **Full stack** (ProjectReference, all 3 libraries) — for nopCommerce plugins that need 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.
|
||||
|
||||
## Documentation Map
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `.github/copilot-instructions.md` | **Domain rules** — single source of truth for all conventions |
|
||||
| `docs/ARCHITECTURE.md` | Dependency graph, project roles, DTO strategies, transaction patterns, logging architecture |
|
||||
| `docs/CONVENTIONS.md` | Naming, patterns, project boundaries, AyCode integration points |
|
||||
| `docs/GLOSSARY.md` | Term definitions — entity/DTO system, data access, services, AyCode types |
|
||||
| `Mango.Nop.Core/README.md` | Core project overview — entity hierarchy, loggers, extensions, models |
|
||||
| `Mango.Nop.Core/docs/DTOS.md` | DTO system — two mapping strategies, all DTO types, GenericAttribute access |
|
||||
| `Mango.Nop.Core/docs/NOP_DEPENDENCIES.md` | NopDependencies pattern — mirror copies, namespace rules, file list |
|
||||
| `Mango.Nop.Data/README.md` | Data project overview — repository and context hierarchy, interfaces |
|
||||
| `Mango.Nop.Data/docs/REPOSITORIES.md` | MgDbTableBase, MgDtoDbTableBase — CRUD hooks, timestamps, delete rules |
|
||||
| `Mango.Nop.Data/docs/TRANSACTIONS.md` | MgDbContextBase — 4 transaction methods, lock strategy, callback contract |
|
||||
| `Mango.Nop.Services/README.md` | Services project overview |
|
||||
| `Mango.Nop.Services/docs/SERVICES.md` | MgBackgroundServiceBase, MgSessionServiceBase, MgEventConsumerBase, MgLockServiceBase |
|
||||
| `Mango.Nop.Services/docs/LOGGING/README.md` | NopLogWriter — AyCode-to-nopCommerce log bridge |
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
# 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)
|
||||
```
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
# Conventions
|
||||
|
||||
## Naming
|
||||
|
||||
- **`Mg` prefix** for all custom types: `MgEntityBase`, `MgOrderDto`, `MgDbTableBase`, `MgDalBase`, etc.
|
||||
- **`I` + name** for interfaces: `IMgDalBase`, `IMgDbTableBase`, `IMgOrderDto`, `IMgLockService`.
|
||||
- **`Dto` suffix** for DTOs wrapping nopCommerce entities: `MgOrderDto`, `MgProductDto`, `MgOrderItemDto`.
|
||||
- **`DbTable` suffix** for repository classes: `MgDbTableBase`, `MgDtoDbTableBase`.
|
||||
- **`Base` suffix** for abstract base classes: `MgEntityBase`, `ModelDtoBase`, `MgBackgroundServiceBase`.
|
||||
- **`Nop` prefix** for nopCommerce bridge types: `NopLogWriter`, `NopLoggerMsSqlNopDataProvider`, `NopCommonConst`.
|
||||
|
||||
## XML Documentation
|
||||
|
||||
`<summary>` — brief, developer-facing, readable in VS IntelliSense tooltip. NO implementation details, NO wire-format / byte-level / perf specifics — those live in `docs/TOPIC/*.md`. Add `<example>` only when usage is non-obvious; otherwise omit.
|
||||
|
||||
## Patterns
|
||||
|
||||
### DTO Bidirectional Mapping
|
||||
- `ModelDtoBase<TMainEntity>` provides `CopyEntityValuesToDto(entity)`, `CopyDtoValuesToEntity(entity)`, and `CreateMainEntity()`. Override all three in concrete DTOs.
|
||||
- Simple DTOs (e.g. `CustomerDto`) — manual property-by-property copy in overrides.
|
||||
- Complex DTOs (e.g. `MgOrderDto`) — use `PropertyHelper.CopyPublicValueTypeProperties(source, target)` for automatic value-type property copy, then manually set reference/navigation properties.
|
||||
|
||||
### LinqToDB Associations
|
||||
- DTOs with navigation properties use `[Association(ThisKey, OtherKey, CanBeNull)]` from LinqToDB.
|
||||
- `ThisKey` = local FK property name, `OtherKey` = target entity property name (typically `Id` or via interface member like `nameof(IMgProductDto.Id)`).
|
||||
|
||||
### NopDependencies Mirror
|
||||
- Entity classes in `NopDependencies/` use the **same namespace** as the original nopCommerce types. Do not change namespaces.
|
||||
- All mirror classes are `partial` — they can be extended but should not be modified directly.
|
||||
|
||||
### GenericAttribute Typed Access
|
||||
- Use `GenericAttributeExtensions.GetValueOrDefault<T>()` / `GetValueOrNull<T>()` / `TryGetValue<T>()` instead of raw string parsing.
|
||||
- Use `AddNewGenericAttribute()` to create new attributes with automatic UTC timestamp.
|
||||
|
||||
### Repository Base Chain
|
||||
- `MgDbTableBase<TEntity>` → `EntityRepository<TEntity>` (nopCommerce). Override virtual `OnInsert`/`OnUpdate`/`OnDelete` hooks, don't replace the chain.
|
||||
- `MgDtoDbTableBase<TDtoEntity, TMainEntity>` → `MgDbTableBase<TDtoEntity>`. **Never call Delete directly** — always use `DeleteMainEntityById(int id)`.
|
||||
|
||||
### Timestamp Interfaces
|
||||
- Entities implementing `ITimeStampCreated` get `Created = DateTime.UtcNow` on insert.
|
||||
- Entities implementing `ITimeStampModified` get `Modified = DateTime.UtcNow` on insert and update.
|
||||
- `ITimeStampInfo` combines both (`Creator`, `Created`, `Modified`).
|
||||
|
||||
### Transaction Pattern
|
||||
- Use `MgDbContextBase.TransactionSafeAsync()` for operations needing global lock (order creation, stock adjustment).
|
||||
- Callback returns `bool` — `true` commits, `false` rolls back.
|
||||
- Exceptions are caught and logged by default (return `false`). Pass `throwException: true` only for fail-fast scenarios.
|
||||
|
||||
### Event Consumer Pattern
|
||||
- Inherit `MgEventConsumerBase` and override relevant `HandleEventAsync` methods.
|
||||
- Base class handles DI of `IMgDbContextBase`, `IHttpContextAccessor`, and `IAcLogWriterBase[]`.
|
||||
- Base provides `CheckAndUpdateProductManageInventoryMethodToManageStock(Product)` helper.
|
||||
|
||||
### Session Pattern
|
||||
- Inherit `MgSessionServiceBase<TSessionItem>` and `MgSessionItemBase`.
|
||||
- Sessions stored in `ConcurrentDictionary<string, TSessionItem>` — thread-safe, in-memory only.
|
||||
- Session items track `SessionId`, `SignaRConnectionId`, `RequestCount`.
|
||||
|
||||
### Logging
|
||||
- Base logging infrastructure (`IAcLoggerBase`, `IAcLogWriterBase`, `AcLoggerBase`, `AcLogItemWriterBase`) — see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md`.
|
||||
- Services create loggers via `new Logger<TCategory>(logWriters.ToArray())` in constructor.
|
||||
- `logWriters` injected as `IEnumerable<IAcLogWriterBase>` — typically contains `NopLogWriter` + other writers.
|
||||
- **Exception:** `MgBackgroundServiceBase` uses `Nop.Services.Logging.ILogger` directly (nopCommerce logger), not the Mango wrapper.
|
||||
|
||||
### Serialization Attributes
|
||||
- `[ToonDescription(...)]` — AyCode metadata for AI/doc tooling. `Purpose`, `BusinessRule`, `TypeRelation`, `RelatedTypes` properties.
|
||||
- `[AcBinarySerializable(false, true, false, true, false)]` — AcBinarySerializer config (see `AyCode.Core/AyCode.Core/docs/BINARY/BINARY_FORMAT.md`). Parameters control serialization behavior for AcSignalR transport (see `AyCode.Core/AyCode.Services/docs/SIGNALR/README.md`).
|
||||
- LinqToDB `[Table(Name = "...")]` and `[Association(...)]` — DB mapping.
|
||||
|
||||
## Project Boundaries
|
||||
|
||||
- `Mango.Nop.Core` — NO nopCommerce runtime dependency. Only NopDependencies mirrors. No `Nop.Data`, `Nop.Services` references.
|
||||
- `Mango.Nop.Data` — depends on nopCommerce data layer (`Nop.Core`, `Nop.Data`). No `Nop.Services` reference.
|
||||
- `Mango.Nop.Services` — depends on full nopCommerce stack (includes `Nop.Services`, `Nop.Web.Framework`).
|
||||
|
||||
## AyCode Integration Points
|
||||
|
||||
Key AyCode types used across these libraries:
|
||||
- `IEntityInt` (AyCode.Interfaces.Entities) — `int Id` entity contract
|
||||
- `IBaseEntity` — defined locally in NopDependencies, mirrors AyCode's concept
|
||||
- `IAcLoggerBase`, `IAcLogWriterBase`, `AcLoggerBase`, `AcLogItemWriterBase` — logging infrastructure (see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md`)
|
||||
- `IAcModelDtoBaseEmpty` — DTO marker interface
|
||||
- `IAcSoftRemoveEntity`, `IAcSoftRemoveEntityInt` — soft-delete contracts
|
||||
- `IForeignKey`, `IForeignCollection<T>` — FK marker interfaces
|
||||
- `ITimeStampCreated`, `ITimeStampModified`, `ITimeStampInfo` — timestamp contracts
|
||||
- `PropertyHelper.CopyPublicValueTypeProperties()` — reflection-based property copy
|
||||
- `TaskHelper.ToThreadPoolTask()` — wraps async work in thread pool
|
||||
- `AcConst` — abstract constants base
|
||||
- `ToonDescription` — metadata attribute for AI tooling
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
# Glossary
|
||||
|
||||
Terminology for the Mango.Nop Libraries. Read this before working on unfamiliar areas.
|
||||
|
||||
## Entity & DTO System
|
||||
|
||||
| Term | Definition |
|
||||
|---|---|
|
||||
| **BaseEntity** | nopCommerce root entity base with `int Id`. Mirror copy in `NopDependencies/`. Namespace: `Nop.Core`. |
|
||||
| **IBaseEntity** | Interface for `BaseEntity` (defined alongside it in NopDependencies). Only `int Id`. |
|
||||
| **MgEntityBase** | Custom entity base — inherits `BaseEntity`, implements `IEntityInt` (AyCode). `ToString()` → `"{TypeName}; Id: {Id}"`. |
|
||||
| **ModelDtoBase** | Non-generic DTO base — only `int Id`. Implements `IModelDtoBase`. |
|
||||
| **ModelDtoBase\<T\>** | Generic DTO base with bidirectional mapping: `CopyEntityValuesToDto()` reads from entity, `CopyDtoValuesToEntity()` writes to entity, `CreateMainEntity()` creates entity from DTO. Uses `Activator.CreateInstance<T>()`. |
|
||||
| **IModelDtoBase** | `IEntityInt` + `IModelDtoBaseEmpty`. Marker for all DTOs with `int Id`. |
|
||||
| **IModelDtoBase\<T\>** | Contract: `CreateMainEntity()`, `CopyDtoValuesToEntity()`, `CopyEntityValuesToDto()`. |
|
||||
| **NopDependencies** | Mirror copies of nopCommerce entity classes in `Mango.Nop.Core`. Same namespaces as originals. Eliminates full nopCommerce dependency for consumers that only need types. |
|
||||
| **GenericAttribute** | nopCommerce polymorphic key-value store. `KeyGroup` = owner type name, `EntityId` = owner ID, `Key` = attribute name, `Value` = string value. `CreatedOrUpdatedDateUTC` tracks last change. |
|
||||
| **PropertyHelper.CopyPublicValueTypeProperties** | AyCode utility — reflection-based copy of all public value-type properties between two objects. Used by complex DTOs (`MgOrderDto`, `MgOrderItemDto`). |
|
||||
| **ToonDescription** | AyCode metadata attribute for AI/doc tooling. Properties: `Purpose`, `BusinessRule`, `TypeRelation`, `RelatedTypes`. |
|
||||
| **AcBinarySerializable** | AyCode binary serialization attribute (AcBinarySerializer, see `AyCode.Core/AyCode.Core/docs/BINARY/BINARY_FORMAT.md`). Configures how a type is serialized for AcSignalR transport (see `AyCode.Core/AyCode.Services/docs/SIGNALR/README.md`). |
|
||||
|
||||
## Data Access
|
||||
|
||||
| Term | Definition |
|
||||
|---|---|
|
||||
| **MgDbTableBase\<T\>** | Repository base wrapping nopCommerce `EntityRepository<T>`. Adds `GetAll()` (`IQueryable<T>`), automatic timestamp management via `ITimeStampCreated`/`ITimeStampModified` interfaces, CRUD hooks (`OnInsert`, `OnUpdate`, `OnDelete`). |
|
||||
| **MgDtoDbTableBase\<TDto, TMain\>** | DTO-aware repository. **Delete operations throw** — must use `DeleteMainEntityById()`. Bridges DTO events → main entity events (`EntityInsertedEvent`, `EntityUpdatedEvent`). |
|
||||
| **MgDbContextBase** | Database context base. Exposes `IRepository<Order>`, `IRepository<OrderItem>`, `IRepository<Product>`, `INopDataProvider`. Provides 4 transaction methods (`Transaction`, `TransactionSafe`, `TransactionAsync`, `TransactionSafeAsync`). |
|
||||
| **MgDalBase\<T\>** | Data Access Layer orchestrator — `Name`, `Context` (typed `TDbContext`), `MutextLock` (cross-process `Mutex`). |
|
||||
| **TransactionSafe** | Transaction with global `SemaphoreSlim` lock. Prevents concurrent modifications. Use for order creation, stock changes. |
|
||||
| **EntityRepository\<T\>** | nopCommerce built-in repository base (`Nop.Data`). `MgDbTableBase` extends this. |
|
||||
| **INopDataProvider** | nopCommerce interface for raw LinqToDB data access. Used by `MgDbContextBase` and `MgDtoDbTableBase`. |
|
||||
|
||||
## Services
|
||||
|
||||
| Term | Definition |
|
||||
|---|---|
|
||||
| **MgBackgroundServiceBase** | Base for hosted background services. Loop: `Task.Delay(interval)` → `OnExecuteAsync()`. Supports pause. Per-iteration exception handling. Uses nopCommerce `ILogger`. |
|
||||
| **MgSessionServiceBase\<T\>** | In-memory session management via `ConcurrentDictionary<string, T>`. Thread-safe. Methods: `GetOrCreateSessionItem`, `TryAddSessionItem`, `TryGetSessionItem`, `TryRemoveSessionItem`, `TryGetSessionItemBySignlaRConnectionId`. |
|
||||
| **MgSessionItemBase** | Session item with `SessionId`, `SignaRConnectionId`, `RequestCount`. Primary constructor: `(string sessionKey)`. |
|
||||
| **MgEventConsumerBase** | nopCommerce event consumer base. Subscribes to: `EntityUpdatedEvent<Product>`, `EntityInsertedEvent<Product>`, `CustomerRegisteredEvent`, `OrderPlacedEvent`, `PageRenderingEvent`, `ProductSearchEvent`. All handlers virtual with empty default. |
|
||||
| **MgLockServiceBase** | `SemaphoreSlim(1)` wrapper. Implements `IMgLockService`. Used by `MgDbContextBase.TransactionSafe*`. |
|
||||
| **NopLogWriter** | Bridges AyCode logging (see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md`) to nopCommerce `Log` table.
|
||||
| **NopLoggerMsSqlNopDataProvider** | Extends `MsSqlNopDataProvider`. Provides `InsertLogItem<T>()` / `InsertLogItemAsync<T>()` with own `TransactionScope(Suppress, ReadUncommitted)` to avoid transaction nesting. |
|
||||
|
||||
## AyCode Types (external, from DLL references)
|
||||
|
||||
| Term | Definition |
|
||||
|---|---|
|
||||
| **IEntityInt** | `int Id` entity contract (AyCode.Interfaces.Entities) |
|
||||
| **IAcLoggerBase** | Logger interface — see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md` (`AyCode.Core.Loggers`) |
|
||||
| **IAcLogWriterBase** | Log writer interface — pluggable output sink (see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md`) |
|
||||
| **AcLoggerBase** | Logger base class with category name and writer array (see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md`) |
|
||||
| **AcLogItemWriterBase\<T\>** | Log writer base for structured log items (see `AyCode.Core/AyCode.Core/docs/LOGGING/README.md`) |
|
||||
| **IAcModelDtoBaseEmpty** | Empty DTO marker interface |
|
||||
| **IAcSoftRemoveEntity** | Soft-delete contract (AyCode) |
|
||||
| **IForeignKey** | FK marker interface |
|
||||
| **IForeignCollection\<T\>** | FK collection marker |
|
||||
| **ITimeStampCreated** | `Created` datetime property |
|
||||
| **ITimeStampModified** | `Modified` datetime property |
|
||||
| **ITimeStampInfo** | Combines `Creator` (int), `Created`, `Modified` |
|
||||
| **AcConst** | Abstract constants base class |
|
||||
| **TaskHelper.ToThreadPoolTask** | Wraps `Func<Task<T>>` into `Task.Run` on thread pool |
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
# Mango.Nop Libraries documentation
|
||||
|
||||
Top-level documentation for the Mango.Nop shared libraries (Layer 2 — shared NopCommerce plugin framework).
|
||||
|
||||
## Reference docs (flat)
|
||||
|
||||
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — Repo architecture overview
|
||||
- [`CONVENTIONS.md`](CONVENTIONS.md) — Coding conventions
|
||||
- [`GLOSSARY.md`](GLOSSARY.md) — Domain glossary
|
||||
|
||||
## Sub-projects with docs
|
||||
|
||||
- `Mango.Nop.Core/docs/` — Core entity mirrors, DTOs, architecture
|
||||
- `Mango.Nop.Data/docs/` — Repository and transaction patterns
|
||||
- `Mango.Nop.Services/docs/` — Service patterns, logger bridge
|
||||
|
||||
## Navigation
|
||||
|
||||
Per the AI Agent Core Protocol (folder navigation rule), start from this README when browsing `docs/`. Single-file reference docs remain flat at this level; multi-file topics live in named subfolders at the sub-project level.
|
||||
|
||||
## See also
|
||||
|
||||
- **Base framework**: `../../../../Aycode/Source/AyCode.Core/` (see each project's `docs/` folder).
|
||||
Loading…
Reference in New Issue