Mango.Nop.Libraries/Mango.Nop.Core/docs/DTOS.md

3.9 KiB

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.