75 lines
3.9 KiB
Markdown
75 lines
3.9 KiB
Markdown
# 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.
|