Tracks the implemented and tested features.
Every cell is a combination that MUST be supported and tested.
Test Summary : see Pragmatic.Mapping.Tests and Pragmatic.Mapping.EFCore.Tests (Mapping 291 tests + the EFCore Postgres suite)
Symbol
Meaning
✅
Implemented & Tested
⚠️
Implemented, needs fix
❌
Not implemented
🔲
Planned
Type Kind
FromEntity
ToEntity
Projection
Test File
class
✅
✅
✅
NullableAndNestedGeneratorTests.PartialClass_GeneratesCorrectly
record
✅
✅
✅
BasicMappingGeneratorTests
struct
✅
🔲
🔲
NullableAndNestedGeneratorTests.PartialStruct_GeneratesCorrectly
record struct
✅
🔲
🔲
BasicMappingGeneratorTests.MapFrom_RecordStruct_GeneratesCorrectly
Source Type Kind
Support
Test
class
✅
All basic tests
record
✅
-
struct
✅
NullableAndNestedGeneratorTests.PartialStruct_GeneratesCorrectly
record struct
✅
-
Note : Null check skipped for value types (structs can’t be null).
Type
Direct Mapping
Test
int
✅
BasicMappingGeneratorTests
int?
✅
NullableAndNestedGeneratorTests.NullableInt_MapsDirectly
string
✅
Multiple tests
string?
✅
NullableAndNestedGeneratorTests.NullableString_MapsDirectly
decimal
✅
NullableAndNestedGeneratorTests.PartialClass_GeneratesCorrectly
DateTime
✅
-
DateTime?
✅
NullableAndNestedGeneratorTests.NullableDateTime_MapsDirectly
Guid
✅
-
Guid?
✅
TypeConversionGeneratorTests.NullableGuid_MapsDirectly
DateOnly
✅
TypeConversionGeneratorTests.DateOnly_MapsDirectly
TimeOnly
✅
TypeConversionGeneratorTests.DateOnly_MapsDirectly
DateOnly?
✅
TypeConversionGeneratorTests.NullableDateOnly_MapsDirectly
TimeOnly?
✅
TypeConversionGeneratorTests.NullableDateOnly_MapsDirectly
enum
✅
TypeConversionGeneratorTests.Enum_SameType_MapsDirectly
enum?
✅
TypeConversionGeneratorTests.NullableEnum_MapsDirectly
Collection Type
Simple Element
DTO Element
Test
T[]
✅
✅
CollectionMappingGeneratorTests.ArrayOfInt, ArrayOfDto
List<T>
✅
✅
CollectionMappingGeneratorTests.ListOfString, ListOfDto
List<T>?
✅
✅
NullableListOfNullableInt, NullableListOfNullableNestedDto
IList<T>
✅
✅
CollectionMappingGeneratorTests.IListOfInt
ICollection<T>
✅
✅
CollectionMappingGeneratorTests.ICollectionOfInt
IEnumerable<T>
✅
✅
CollectionMappingGeneratorTests.IEnumerableOfInt
IReadOnlyList<T>
✅
🔲
CollectionMappingGeneratorTests.IReadOnlyListOfInt
IReadOnlyCollection<T>
✅
🔲
CollectionMappingGeneratorTests.IReadOnlyCollectionOfInt
HashSet<T>
✅
🔲
CollectionMappingGeneratorTests.HashSetOfInt
Scenario
Status
Test
Single non-nullable DTO
✅
NullableAndNestedGeneratorTests.NestedDto_MapsWithFromEntity
Single nullable DTO
✅
NullableAndNestedGeneratorTests.NullableNestedDto_HandlesNullSafely
Array of DTO
✅
NullableAndNestedGeneratorTests.ArrayOfNestedDto_MapsEachElement
List of DTO
✅
CollectionMappingGeneratorTests.ListOfDto_MapsEachElement
List of nullable DTO
✅
NullableAndNestedGeneratorTests.NullableListOfNullableNestedDto_HandlesCorrectly
Implementation : Uses SymbolDisplayFormat.FullyQualifiedFormat for type names to avoid namespace resolution issues.
Dictionary Type
Simple Value
DTO Value
Test
Dictionary<K,V>
✅
✅
CollectionMappingGeneratorTests.DictionaryStringInt, TypeConversionGeneratorTests.DictionaryWithDtoValue
IDictionary<K,V>
🔲
🔲
-
IReadOnlyDictionary<K,V>
🔲
🔲
-
Conversion
Status
Test
int → long
✅
TypeConversionGeneratorTests.IntToLong_ImplicitConversion
int → decimal
✅
TypeConversionGeneratorTests.IntToDecimal_ImplicitConversion
int? → int (no default)
⚠️ CS0266
TypeConversionGeneratorTests.NullableIntToInt_WithoutDefault_ShouldCompile
int? → int (with default)
✅
AdvancedMappingGeneratorTests.MapProperty_WithDefault_UsesDefaultWhenNull
Note : C# implicit conversions (widening) work automatically. Nullable → Non-nullable requires [MapProperty(Default=)].
Conversion
Status
Generated Code
Test
int → string
✅
.ToString()
TypeConversionGeneratorTests.IntToString
string → int
✅
int.Parse()
TypeConversionGeneratorTests.StringToInt
enum → string
✅
.ToString()
TypeConversionGeneratorTests.EnumToString
string → enum
✅
Enum.Parse<T>()
TypeConversionGeneratorTests.StringToEnum
Guid → string
✅
.ToString()
TypeConversionGeneratorTests.GuidToString
string → Guid
✅
Guid.Parse()
TypeConversionGeneratorTests.StringToGuid
DateTime → DateOnly
✅
DateOnly.FromDateTime()
TypeConversionGeneratorTests.DateTimeToDateOnly
DateOnly → DateTime
✅
.ToDateTime(TimeOnly.MinValue)
TypeConversionGeneratorTests.DateOnlyToDateTime
DateTime → TimeOnly
✅
TimeOnly.FromDateTime()
TypeConversionGeneratorTests.DateTimeToTimeOnly
decimal → string
✅
.ToString()
TypeConversionGeneratorTests.DecimalToString
string → decimal
✅
decimal.Parse()
TypeConversionGeneratorTests.StringToDecimal
bool → string
✅
.ToString()
TypeConversionGeneratorTests.BoolToString
string → bool
✅
bool.Parse()
TypeConversionGeneratorTests.StringToBool
DateTime → string
✅
.ToString()
TypeConversionGeneratorTests.DateTimeToString
string → DateTime
✅
DateTime.Parse()
TypeConversionGeneratorTests.StringToDateTime
string → DateOnly
✅
DateOnly.Parse()
TypeConversionGeneratorTests.StringToDateOnly
string → TimeOnly
✅
TimeOnly.Parse()
TypeConversionGeneratorTests.StringToTimeOnly
Implementation : Generator detects source/target type mismatch and applies known conversion patterns automatically.
Nullable variants also supported (e.g., int? → string, string → int?).
Source → Target
Status
Test
List<T> → T[]
✅
TypeConversionGeneratorTests.ListToArray_Conversion
T[] → List<T>
✅
TypeConversionGeneratorTests.ArrayToList_Conversion
IEnumerable<T> → List<T>
✅
TypeConversionGeneratorTests.IEnumerableToList_Conversion
List<T> → IEnumerable<T>
✅
TypeConversionGeneratorTests.ListToIEnumerable_Conversion
List<T> → HashSet<T>
✅
TypeConversionGeneratorTests.ListToHashSet_Conversion
T[] → IReadOnlyList<T>
✅
TypeConversionGeneratorTests.ArrayToIReadOnlyList_Conversion
Attribute
Status
Test
[MapFrom<T>]
✅
All FromEntity tests
[MapTo<T>]
✅
AdvancedMappingGeneratorTests.MapTo_*
[MapProperty] (path / Default / Format / Target / Separator)
✅
AdvancedMappingGeneratorTests.MapProperty_*
[MapIgnore]
✅
AdvancedMappingGeneratorTests.MapIgnore_*
[MapConverter<T>] (property-level)
✅
AdvancedMappingGeneratorTests.Converter_*
[MapConverter<T>] (class-level, signature-matched)
✅
ConventionAndTypeLevelTests
[MapConstructor]
✅
MapConstructorAndSeparatorGeneratorTests
[MapCondition] (runtime gate, and projection gate for an expression-bodied predicate; PRAG0329/0332)
✅
DiagnosticTests, RuntimeDispatchTests, ADetailInOneProjectionTests
[MapDerived<TS,TD>] (polymorphic; PRAG0330/0331)
✅
DiagnosticTests, RuntimeDispatchTests
[GenerateProjection(MaxDepth=)]
✅
ProjectionGeneratorTests, DiagnosticTests (PRAG0327)
[GenerateBodyOnlyVariant]
✅
BodyOnlyVariantGeneratorTests
Strategy
Status
Test
Direct name match
✅
All basic tests
Case-insensitive match
✅
-
Flattening (AddressCity → Address.City)
✅
AdvancedMappingGeneratorTests.Flattening_*
Concatenation (FullName → FirstName + LastName)
✅
BasicMappingGeneratorTests.MapFrom_WithFullNameConvention
Explicit path via [MapProperty]
✅
AdvancedMappingGeneratorTests.MapProperty_*
Feature
Status
Test
ID property exclusion in ToEntity
✅
AdvancedMappingGeneratorTests.MapTo_ExcludesIdByDefault
Init-only properties
✅
-
Required properties
✅
-
Circular reference detection
✅
-
Null safety
✅
NullableAndNestedGeneratorTests.*
Method
Status
Struct Support
Test
FromEntity(entity)
✅
✅
All FromEntity tests
ToEntity()
✅
🔲
MapTo tests
Projection
✅
🔲
ProjectionGeneratorTests
Note : ApplyTo(entity) is generated by Pragmatic.Mapping for DTOs marked with [MapTo<T>] (updates an existing entity, partial-update semantics). It is suppressed only when the DTO also carries [Patch<T>] or [Mutation<T>], in which case the respective generator owns the update path.
Hook
Status
Test
partial void BeforeMapping()
✅
-
partial void CustomizeMapping()
✅
-
MappingContext struct
✅
-
DTO Accessibility
Support
Extensions Class
Test
public
✅
public static
All basic tests
internal
✅
internal static
AdvancedMappingGeneratorTests.MapFrom_InternalClass_GeneratesInternalMethods
private (nested)
🔲
-
-
Bug
Status
Fix
Struct source + Ensure.ThrowIfNull
✅ FIXED
Skip null check for value types
Nullable DTO type name includes ?
✅ FIXED
Use SymbolDisplayFormat.FullyQualifiedFormat
List<string> treated as DTO collection
✅ FIXED
Check IsElementSimple in AnalyzeNestedDto
Extensions class ignores accessibility
✅ FIXED
Added ParseAccessibility() in MappingExtensionsTemplate
[MapProperty(Default=)] not implemented
✅ FIXED
Added fallback resolution by property name when only Default is specified
Issue
Status
Fix
Test
[MapProperty(Format=)] for non-DateTime
✅ FIXED
Added format support to GenerateNumericToString and GenerateToString
AdvancedMappingGeneratorTests.MapProperty_WithFormat_*
[MapProperty] + [MapConverter] together
✅ FIXED
Moved converter check before MapProperty check, passed converter to CreateExplicitMapping
AdvancedMappingGeneratorTests.MapProperty_WithMapConverter_*
Test File
Tests
Passing
Failing
BasicMappingGeneratorTests
7
7
0
AdvancedMappingGeneratorTests
16
16
0
CollectionMappingGeneratorTests
9
9
0
ProjectionGeneratorTests
5
5
0
NullableAndNestedGeneratorTests
9
9
0
TypeConversionGeneratorTests
51
51
0
AutomaticConversionGeneratorTests
12
12
0
AutoDefaultGeneratorTests
12
12
0
DiagnosticTests
4
4
0
TOTAL
125
125
0
Note : EF Core integration tests use TestContainers with PostgreSQL.
Sample File
Features Demonstrated
BasicMappingSample
FromEntity, extension methods, collection mapping, FullName concatenation, flattening
NestedMappingSample
Nested DTOs, collection of DTOs, flattened DTO
BidirectionalMappingSample
MapFrom + MapTo, ToEntity()
StructMappingSample
record struct, zero-allocation, Projection
ProjectionSample
GenerateProjection, Expression<Func<T,TDto>>
TypeConversionSample
ToString, Parse, DateTime↔DateOnly, Dictionary with DTOs, Inheritance
NullableAndAdvancedSample
Auto-default, Collection type conversions, Circular references, DateOnly→DateTime
TypeCombinationsSample
class→class, class→record, record→record, record→class, MapIgnore
AdvancedAttributesSample
MapIgnore, MapConverter, MapProperty(path), MapProperty(Format)
Core source generator (FromEntity, ToEntity, Projection)
All property types (simple, nullable, collections, nested DTOs)
Property resolution (direct match, flattening, concatenation)
MapProperty with Default value
MapIgnore, MapConverter attributes
EF Core integration package with extension methods
Comprehensive samples (Basic, Nested, Bidirectional, Struct, Projection, TypeConversion)
README documentation
P0: Auto-default for primitives (GetValueOrDefault, ?? “”)
P1: Type conversions (ToString, Parse, enum↔string, Guid↔string)
P2: DateTime conversions (DateTime↔DateOnly/TimeOnly)
P3: Dictionary with DTO values, Inheritance mapping
Feature
Description
Status
Auto-default for primitives
int? → int uses GetValueOrDefault(), string? → string uses ?? ""
✅ Implemented
Auto-default in Projection
Uses ?? 0, ?? "", ?? Guid.Empty for EF Core Expression Tree compatibility
✅ Implemented
Feature
Description
Status
Test
ToString conversions
int → string via .ToString()
✅
TypeConversionGeneratorTests.IntToString
Enum → string
Status.Active → "Active"
✅
TypeConversionGeneratorTests.EnumToString
Parse conversions
string → int via int.Parse()
✅
TypeConversionGeneratorTests.StringToInt
Guid ↔ string
Guid.ToString() / Guid.Parse()
✅
TypeConversionGeneratorTests.GuidToString/StringToGuid
Feature
Description
Status
Test
DateTime → DateOnly
DateOnly.FromDateTime()
✅
TypeConversionGeneratorTests.DateTimeToDateOnly
DateTime → TimeOnly
TimeOnly.FromDateTime()
✅
TypeConversionGeneratorTests.DateTimeToTimeOnly
DateOnly → DateTime
.ToDateTime(TimeOnly.MinValue)
✅
TypeConversionGeneratorTests.DateOnlyToDateTime
String ↔ decimal
Parse/ToString
✅
TypeConversionGeneratorTests.StringToDecimal/DecimalToString
Feature
Description
Status
Test
Dictionary with DTO values
Dictionary<string, CategoryDto>
✅
TypeConversionGeneratorTests.DictionaryWithDtoValue
Inheritance mapping
Base → Derived DTO properties
✅
TypeConversionGeneratorTests.InheritedProperties
Interface-based DTOs
IUserDto
🔲
Future
Scenario
Category
Test File
Status
Same-name property mapping
Basic
BasicMappingGeneratorTests
✅
Different-name property mapping
Advanced
AdvancedMappingGeneratorTests
✅
Custom converter
Advanced
AdvancedMappingGeneratorTests
✅
Nested DTO mapping
Nested
NullableAndNestedGeneratorTests
✅
Collection of DTOs
Collection
CollectionMappingGeneratorTests
✅
Scenario
Test
Status
Non-partial class skips generation
DiagnosticTests.NonPartialClass_SkipsGeneration
✅
Partial class generates correctly
DiagnosticTests.PartialClass_GeneratesCorrectly
✅
Unmatched property uses default
DiagnosticTests.UnmatchedProperty_GeneratesWithDefault
✅
Invalid MapProperty path
DiagnosticTests.MapProperty_WithInvalidPath_CompilesButUnmapped
✅
[GenerateProjection] without [MapFrom]
DiagnosticTests.GenerateProjection_WithoutMapFrom_SkipsProjection
✅
[MapIgnore] takes precedence
DiagnosticTests.MapIgnore_TakesPrecedence_OverMapProperty
✅
Nested DTO with [MapFrom]
DiagnosticTests.NestedDto_WithMapFrom_GeneratesCorrectly
✅
Collection with simple elements
DiagnosticTests.Collection_WithSimpleElements_MapsDirectly
✅
Struct source skips null check
DiagnosticTests.StructSource_SkipsNullCheck
✅
Class source includes null check
DiagnosticTests.ClassSource_IncludesNullCheck
✅
MapTo excludes ID by default
DiagnosticTests.MapTo_ExcludesIdByDefault
✅
Internal class generates internal extensions
DiagnosticTests.InternalClass_GeneratesInternalExtensions
✅
Empty DTO generates minimal
DiagnosticTests.EmptyDto_GeneratesMinimalMapping
✅
Multiple [MapFrom] causes error
DiagnosticTests.MultipleMapFrom_CausesDuplicateAttributeError
✅
Bidirectional mapping
DiagnosticTests.MapFrom_And_MapTo_OnSameType_GeneratesBothMethods
✅
When using EF Core, navigation properties require explicit Include() calls when using FromEntity():
// ⚠️ PROBLEM: Lazy loading or null navigation properties
var users = await _db.Users. ToListAsync ();
var dtos = users. ToUserDto (); // Orders will be null/empty!
// ✅ SOLUTION 1: Manual Include
var users = await _db.Users
var dtos = users. ToUserDto ();
// ✅ SOLUTION 2: Use Projection (BEST - optimized SQL)
var dtos = await _db.Users
. Select (UserDto.Projection)
Feature
Status
Description
SelectDto(projection)
✅
Projects query using expression
ToListDtoAsync(projection)
✅
Async projection to list
FirstOrDefaultDtoAsync(projection)
✅
Async single item projection
SingleOrDefaultDtoAsync(projection)
✅
Async single-or-default projection
ToArrayDtoAsync(projection)
✅
Async projection to array
ToPagedDtoAsync(projection, page, size)
✅
Paginated projection with metadata
ToSliceDtoAsync(projection, offset, limit)
✅
Offset/limit projection
// Projection-based (generates optimized SQL)
var dtos = await _db.Users
. ToListDtoAsync (UserDto.Projection);
var page = await _db.Users
. ToPagedDtoAsync (UserDto.Projection, pageNumber : 1 , pageSize : 20 );
// page.Items, page.TotalCount, page.TotalPages, page.HasNextPage, etc.
Feature
Status
Description
RequiredIncludes<TDto>()
🔲 Planned
Returns Include chain for FromEntity
WithRequiredIncludes<TDto>()
🔲 Planned
Applies required includes to query
Note : Auto-Include features require DomainEntity metadata (not yet implemented).