This sample demonstrates the EnumMappingGenerator in action with realistic enum mapping scenarios including special case handling, bidirectional mappings, and case-insensitive matching.
sample/Atc.SourceGenerators.EnumMapping/
cd sample/Atc.SourceGenerators.EnumMapping
dotnet runExpected output:
=== Atc.SourceGenerators - Enum Mapping Sample ===
1. Testing PetStatusEntity β PetStatusDto mapping:
- Special case: None β Unknown
- Bidirectional: true
None β Unknown
Available β Available
Pending β Pending
Adopted β Adopted
2. Testing PetStatusDto β PetStatusEntity (reverse mapping):
Unknown β None
3. Testing FeatureState β FeatureFlag mapping:
- Exact name matching
- Bidirectional: false
Active β Active
Inactive β Inactive
Testing β Testing
4. Testing case-insensitive matching:
All enum values match regardless of casing
5. Performance characteristics:
β Zero runtime cost - pure switch expressions
β Compile-time safety with exhaustive checking
β ArgumentOutOfRangeException for unmapped values
=== All tests completed successfully! ===
PetStatusEntity.cs:
[MapTo(typeof(PetStatusDto), Bidirectional = true)]
public enum PetStatusEntity
{
None, // Special case: maps to PetStatusDto.Unknown
Pending,
Available,
Adopted,
}PetStatusDto.cs:
public enum PetStatusDto
{
Unknown, // Special case: maps from PetStatusEntity.None
Available,
Pending,
Adopted,
}Key Points:
Noneautomatically maps toUnknown(common pattern)Bidirectional = truegenerates both forward and reverse mappings- All other values map by exact name match
FeatureState.cs:
[MapTo(typeof(FeatureFlag))]
public enum FeatureState
{
Active, // Exact match to FeatureFlag.Active
Inactive, // Exact match to FeatureFlag.Inactive
Testing, // Exact match to FeatureFlag.Testing
}FeatureFlag.cs:
public enum FeatureFlag
{
Active, // Exact match from FeatureState.Active
Inactive, // Exact match from FeatureState.Inactive
Testing, // Exact match from FeatureState.Testing
}Key Points:
- All values match by exact name
- Unidirectional mapping (Bidirectional = false)
sample/Atc.SourceGenerators.EnumMapping/
βββ Atc.SourceGenerators.EnumMapping.csproj
βββ GlobalUsings.cs
βββ Program.cs
βββ Enums/
βββ PetStatusEntity.cs (Database layer enum)
βββ PetStatusDto.cs (API layer enum)
βββ FeatureState.cs (Domain layer enum)
βββ FeatureFlag.cs (Configuration layer enum)
The source generator creates extension methods in the Atc.Mapping namespace:
EnumMappingExtensions.g.cs (simplified):
namespace Atc.Mapping;
public static class EnumMappingExtensions
{
// Forward mapping: PetStatusEntity β PetStatusDto
public static PetStatusDto MapToPetStatusDto(this PetStatusEntity source)
{
return source switch
{
PetStatusEntity.None => PetStatusDto.Unknown, // Special case
PetStatusEntity.Pending => PetStatusDto.Pending,
PetStatusEntity.Available => PetStatusDto.Available,
PetStatusEntity.Adopted => PetStatusDto.Adopted,
_ => throw new ArgumentOutOfRangeException(nameof(source), source, "Unmapped enum value"),
};
}
// Reverse mapping: PetStatusDto β PetStatusEntity (Bidirectional = true)
public static PetStatusEntity MapToPetStatusEntity(this PetStatusDto source)
{
return source switch
{
PetStatusDto.Unknown => PetStatusEntity.None, // Special case
PetStatusDto.Available => PetStatusEntity.Available,
PetStatusDto.Pending => PetStatusEntity.Pending,
PetStatusDto.Adopted => PetStatusEntity.Adopted,
_ => throw new ArgumentOutOfRangeException(nameof(source), source, "Unmapped enum value"),
};
}
// Forward mapping: FeatureState β FeatureFlag
public static FeatureFlag MapToFeatureFlag(this FeatureState source)
{
return source switch
{
FeatureState.Active => FeatureFlag.Active,
FeatureState.Inactive => FeatureFlag.Inactive,
FeatureState.Testing => FeatureFlag.Testing,
_ => throw new ArgumentOutOfRangeException(nameof(source), source, "Unmapped enum value"),
};
}
}The generator automatically recognizes common enum naming patterns:
| Pattern | Equivalent Values | Notes |
|---|---|---|
| Zero/Null States | None β Unknown, Default, NotSet | Common default state mapping |
| Active States | Active β Enabled, On, Running | Service/feature activation |
| Inactive States | Inactive β Disabled, Off, Stopped | Service/feature deactivation |
| Deletion States | Deleted β Removed, Archived | Soft delete patterns |
| Pending States | Pending β InProgress, Processing | Async operation states |
| Completion States | Completed β Done, Finished | Task completion states |
Example:
// Database enum
public enum ServiceStatusEntity
{
None, // Maps to Unknown in API
Active, // Maps to Enabled in API
Inactive // Maps to Disabled in API
}
// API enum
public enum ServiceStatus
{
Unknown, // Maps from None in database
Enabled, // Maps from Active in database
Disabled // Maps from Inactive in database
}Smart matching: The generator uses exact name matching first, then falls back to case-insensitive matching, and finally checks for special case patterns. This ensures predictable behavior while supporting common enum naming variations.
With Bidirectional = true:
[MapTo(typeof(PetStatusDto), Bidirectional = true)]
public enum PetStatusEntity { ... }You get two methods:
PetStatusEntity.MapToPetStatusDto()(forward)PetStatusDto.MapToPetStatusEntity()(reverse)
Enum values match regardless of casing:
// These all match:
SourceEnum.ACTIVE β TargetEnum.Active
SourceEnum.active β TargetEnum.Active
SourceEnum.Active β TargetEnum.Active
SourceEnum.AcTiVe β TargetEnum.ActiveUnmapped values generate warnings:
Warning ATCENUM002: Enum value 'SourceStatus.Deleted' has no matching value in target enum 'TargetStatus'
Unmapped values throw at runtime:
var status = SourceStatus.Deleted; // Unmapped value
var dto = status.MapToTargetDto(); // Throws ArgumentOutOfRangeExceptionUse Case: Multi-layer architecture with enum separation
// Database layer
[MapTo(typeof(Domain.Status))]
public enum StatusEntity
{
None,
Active,
Inactive,
}
// Domain layer
[MapTo(typeof(Api.StatusDto))]
public enum Status
{
Unknown,
Active,
Inactive,
}
// API layer
public enum StatusDto
{
Unknown,
Active,
Inactive,
}
// Complete chain
var entity = database.GetStatus(); // StatusEntity.None
var domain = entity.MapToStatus(); // Status.Unknown
var dto = domain.MapToStatusDto(); // StatusDto.UnknownUse Case: Feature flags with consistent naming
// Configuration (appsettings.json representation)
[MapTo(typeof(FeatureState))]
public enum FeatureFlag
{
Active,
Inactive,
}
// Domain (business logic representation)
public enum FeatureState
{
Active, // β FeatureFlag.Active (exact match)
Inactive, // β FeatureFlag.Inactive (exact match)
}
// Usage
var config = configuration.GetValue<FeatureFlag>("MyFeature");
var state = config.MapToFeatureState();
if (state == FeatureState.Active)
{
// Feature is active
}Use Case: Third-party API integration with case normalization
// External API enum (from SDK)
[MapTo(typeof(InternalStatus))]
public enum ExternalStatus
{
NONE,
PENDING,
ACTIVE,
}
// Internal domain enum (your naming)
public enum InternalStatus
{
Unknown, // β ExternalStatus.NONE (special case: None β Unknown)
Pending, // β ExternalStatus.PENDING (case-insensitive)
Active, // β ExternalStatus.ACTIVE (case-insensitive)
}
// Usage
var external = apiClient.GetStatus(); // ExternalStatus.NONE
var internal = external.MapToInternalStatus(); // InternalStatus.UnknownThis pattern is used in the PetStore sample to separate enum concerns across layers:
PetStatusEntity (DataAccess)
β MapToPetStatus()
PetStatus (Domain)
β MapToPetStatus() [different types, same method name]
PetStatus (Api.Contract)
Each layer has its own enum definition, and mappings are generated automatically.
- No Reflection: All mappings use pure switch expressions for maximum performance
- AOT Compatible: Works with Native AOT compilation
- Type Safe: Compiler errors if target types are incorrect
- IntelliSense Support: Generated methods appear in IDE autocomplete
- Object Mapping Sample - For class-to-class mappings
- PetStore Sample - Complete application using all generators
- Dependency Registration Sample - DI registration
- Options Binding Sample - Configuration binding
Need more examples? Check the EnumMapping Generator documentation for comprehensive guides and patterns.