A collection of Roslyn C# source generators for .NET that eliminate boilerplate code and improve developer productivity. All generators are designed with Native AOT compatibility in focus, enabling faster startup times, smaller deployment sizes, and optimal performance for modern cloud-native applications.
Why Choose Atc Source Generators?
- π― Zero boilerplate - Attribute-based approach eliminates repetitive code
- β‘ Compile-time generation - Catch errors during build, not at runtime
- π Native AOT ready - Zero reflection, fully trimming-safe for modern .NET
- π§© Multi-project architecture - Smart naming for clean layered applications
- π‘οΈ Type-safe - Full IntelliSense and compile-time validation
- π¦ Single package - Install once, use all generators
- β‘ DependencyRegistrationGenerator - Automatic DI service registration with attributes
- βοΈ OptionsBindingGenerator - Automatic configuration binding to strongly-typed options classes
- πΊοΈ MappingGenerator - Automatic object-to-object mapping with type safety
- π EnumMappingGenerator - Automatic enum-to-enum mapping with intelligent matching
All four generators work together seamlessly in a typical 3-layer architecture:
// 1οΈβ£ Domain Layer - Your business logic
[MapTo(typeof(PetStatusDto), Bidirectional = true)]
public enum PetStatus { Available, Adopted }
[MapTo(typeof(PetDto))]
public partial class Pet
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public PetStatus Status { get; set; }
}
[Registration(Lifetime.Scoped)]
public class PetService : IPetService
{
public async Task<Pet> GetPetAsync(Guid id) { /* ... */ }
}
[OptionsBinding("PetStore")]
public partial class PetStoreOptions
{
[Required] public int MaxPetsPerPage { get; set; }
}
// 2οΈβ£ Program.cs - One line per concern
using Atc.DependencyInjection;
using Atc.Mapping;
// Register all services from Domain layer
builder.Services.AddDependencyRegistrationsFromDomain();
// Bind all options from Domain layer
builder.Services.AddOptionsFromDomain(builder.Configuration);
// 3οΈβ£ Usage - Clean and type-safe
app.MapGet("/pets/{id}", async (Guid id, IPetService service) =>
{
var pet = await service.GetPetAsync(id);
return Results.Ok(pet.MapToPetDto()); // β¨ Generated mapping
});Result: Zero boilerplate, full type safety, Native AOT ready! π
All generators are distributed in a single NuGet package. Install once to use all features.
Required:
dotnet add package Atc.SourceGeneratorsOptional (recommended for better IntelliSense):
dotnet add package Atc.SourceGenerators.AnnotationsOr in your .csproj:
<ItemGroup>
<!-- Required: Source generator -->
<PackageReference Include="Atc.SourceGenerators" Version="1.0.0" />
<!-- Optional: Attribute definitions with XML documentation -->
<PackageReference Include="Atc.SourceGenerators.Annotations" Version="1.0.0" />
</ItemGroup>Note: The generator emits fallback attributes automatically, so the Annotations package is optional. However, it provides better XML documentation and IntelliSense. If you include it, suppress the expected CS0436 warning: <NoWarn>$(NoWarn);CS0436</NoWarn>
Stop writing repetitive service registration code. Decorate your services with [Registration] and let the generator handle the rest.
- Complete Guide - In-depth documentation with examples
- Quick Start - PetStore 3-layer architecture tutorial
- Multi-Project Setup - Working with multiple projects
- Auto-Detection - Understanding automatic interface detection
- Sample Projects - Working code examples with architecture diagrams
// Program.cs - Manual registration hell π«
services.AddScoped<IUserService, UserService>();
services.AddScoped<IOrderService, OrderService>();
services.AddScoped<IPetRepository, PetRepository>();
services.AddSingleton<ICacheService, CacheService>();
services.AddTransient<ILogger, Logger>();
services.AddScoped<IPetService, PetService>();
services.AddScoped<IEmailService, EmailService>();
// ... 50+ more lines of registration code
// ... spread across multiple files
// ... easy to forget or get wrong// Your services - Clean, declarative, self-documenting β¨
[Registration(Lifetime.Scoped)]
public class UserService : IUserService { }
[Registration(Lifetime.Scoped)]
public class OrderService : IOrderService { }
[Registration]
public class CacheService : ICacheService { }
// Program.cs - One line per project (with smart naming!)
using Atc.DependencyInjection;
builder.Services.AddDependencyRegistrationsFromApi();
builder.Services.AddDependencyRegistrationsFromDomain();
builder.Services.AddDependencyRegistrationsFromDataAccess();- π― Interface Auto-Detection: Automatically registers against all implemented interfaces - no
As = typeof(IService)needed - π· Generic Interface Registration: Full support for open generics like
IRepository<T>andIHandler<TRequest, TResponse> - π Keyed Service Registration: Multiple implementations of the same interface with different keys (.NET 8+)
- π Factory Method Registration: Custom initialization logic via static factory methods
- π¦ Instance Registration: Register pre-created singleton instances via static fields, properties, or methods
- π TryAdd Registration*: Conditional registration for default implementations (library pattern)
- βοΈ Conditional Registration: Register services based on configuration values (feature flags, environment-specific services)
- π¨ Decorator Pattern Support: Wrap services with cross-cutting concerns (logging, caching, validation) using
Decorator = true - π« Assembly Scanning Filters: Exclude types by namespace, pattern (wildcards), or interface implementation
- π― Runtime Filtering: Exclude services when calling registration methods via optional parameters (different apps, different service subsets)
- π Transitive Registration: Automatically discover and register services from referenced assemblies (4 overloads: default, auto-detect all, selective by name, selective multiple)
- π§Ή Smart Filtering: System interfaces (IDisposable, etc.) are automatically excluded
- π Multi-Interface Registration: Implementing multiple interfaces? Registers against all of them
- π Hosted Service Support: Automatically detects BackgroundService and IHostedService implementations and uses AddHostedService()
- β¨ Smart Naming: Generates clean method names using suffixes when unique, full names when conflicts exist
- β‘ Zero Runtime Overhead: All code generated at compile time
- π Native AOT Compatible: No reflection or runtime code generation - fully trimming-safe
- ποΈ Multi-Project Support: Works seamlessly across layered architectures
- π‘οΈ Compile-Time Validation: Diagnostics for common errors catch issues before runtime
- π¦ Flexible Lifetimes: Singleton (default), Scoped, and Transient support
using Atc.DependencyInjection;
// That's it! Auto-detected as IUserService
[Registration(Lifetime.Scoped)]
public class UserService : IUserService
{
public void CreateUser(string name) { }
}
// Multiple interfaces? No problem - registers against ALL of them
[Registration]
public class EmailService : IEmailService, INotificationService { }
// Need both interface AND concrete type?
[Registration(AsSelf = true)]
public class ReportService : IReportService { }
// Custom initialization logic via factory method
[Registration(Lifetime.Scoped, As = typeof(IEmailSender), Factory = nameof(Create))]
public class EmailSender : IEmailSender
{
private EmailSender(string apiKey) { }
public static IEmailSender Create(IServiceProvider sp)
{
var config = sp.GetRequiredService<IConfiguration>();
return new EmailSender(config["Email:ApiKey"]);
}
}
// Default implementation for libraries (can be overridden by consumers)
[Registration(As = typeof(ILogger), TryAdd = true)]
public class DefaultLogger : ILogger
{
public void Log(string message) => Console.WriteLine(message);
}
// Decorator pattern - wrap services with cross-cutting concerns
[Registration(Lifetime.Scoped, As = typeof(IOrderService), Decorator = true)]
public class LoggingOrderServiceDecorator : IOrderService
{
private readonly IOrderService inner;
private readonly ILogger logger;
public LoggingOrderServiceDecorator(IOrderService inner, ILogger logger)
{
this.inner = inner;
this.logger = logger;
}
public async Task PlaceOrderAsync(string orderId)
{
logger.Log($"Before placing order {orderId}");
await inner.PlaceOrderAsync(orderId);
logger.Log($"After placing order {orderId}");
}
}[Registration] // Singleton (default)
[Registration(Lifetime.Singleton)] // Explicit singleton
[Registration(Lifetime.Scoped)] // Per-request (web apps)
[Registration(Lifetime.Transient)] // New instance every timeGet errors at compile time, not runtime:
| ID | Description |
|---|---|
| ATCDIR001 | As parameter must be an interface or abstract class type |
| ATCDIR002 | Class must implement the specified interface or inherit from abstract class |
| ATCDIR003 | Duplicate registration with different lifetimes |
| ATCDIR004 | Hosted services must use Singleton lifetime |
| ATCDIR005 | Factory method not found |
| ATCDIR006 | Factory method has invalid signature |
Eliminate boilerplate configuration binding code. Decorate your options classes with [OptionsBinding] and let the generator create type-safe configuration bindings automatically. Supports DataAnnotations validation, startup validation, fail-fast validation for missing configuration sections (ErrorOnMissingKeys), and custom IValidateOptions<T> validators for complex business rules.
- Options Binding Guide - Full documentation with examples
- Sample Projects - Working examples with architecture diagrams
// Manual options binding - repetitive and error-prone π«
services.AddOptions<DatabaseOptions>()
.Bind(configuration.GetSection("Database"))
.ValidateDataAnnotations()
.ValidateOnStart();
services.AddOptions<ApiOptions>()
.Bind(configuration.GetSection("App:Api"))
.ValidateDataAnnotations()
.ValidateOnStart();
services.AddOptions<LoggingOptions>()
.Bind(configuration.GetSection("Logging"))
.ValidateOnStart();
// ... repeated for every options class// Your options classes - Clean and declarative β¨
[OptionsBinding("Database", ValidateDataAnnotations = true, ValidateOnStart = true)]
public partial class DatabaseOptions
{
[Required]
public string ConnectionString { get; set; }
}
[OptionsBinding("App:Api", ValidateDataAnnotations = true)]
public partial class ApiOptions
{
public string BaseUrl { get; set; }
}
[OptionsBinding] // Section name auto-inferred as "LoggingOptions"
public partial class LoggingOptions
{
public string Level { get; set; }
}
// Program.cs - One line binds all options (with smart naming!)
services.AddOptionsFromApp(configuration);- π§ Automatic Section Name Inference: Smart resolution from explicit names, const fields (
SectionName,NameTitle,Name), or auto-inferred from class names - π Built-in Validation: Integrated DataAnnotations validation (
ValidateDataAnnotations) and startup validation (ValidateOnStart) - π― Custom Validation: Support for
IValidateOptions<T>for complex business rules beyond DataAnnotations - π Configuration Change Callbacks: Auto-generated IHostedService for OnChange notifications with Monitor lifetime - perfect for feature flags and runtime config updates
- π§ Post-Configuration Support: Normalize or transform values after binding with
PostConfigurecallbacks (e.g., ensure paths have trailing slashes, lowercase URLs) - π Named Options: Multiple configurations of the same options type with different names (e.g., Primary/Secondary email servers)
- π― Explicit Section Paths: Support for nested sections like
"App:Database"or"Services:Email" - π Nested Subsection Binding: Automatic binding of complex properties to configuration subsections (e.g.,
StorageOptions.Database.Retryβ"Storage:Database:Retry") - π¦ Multiple Options Classes: Register multiple configuration sections in a single assembly with one method call
- ποΈ Multi-Project Support: Smart naming generates assembly-specific extension methods (e.g.,
AddOptionsFromDomain(),AddOptionsFromDataAccess()) - π Transitive Registration: Automatically discover and register options from referenced assemblies (4 overloads: default, auto-detect all, selective by name, selective multiple)
- β±οΈ Flexible Lifetimes: Choose between Singleton (
IOptions<T>), Scoped (IOptionsSnapshot<T>), or Monitor (IOptionsMonitor<T>) patterns - β‘ Native AOT Ready: Pure compile-time code generation with zero reflection, fully trimming-safe for modern .NET deployments
- π‘οΈ Compile-Time Safety: Catch configuration errors during build, not at runtime
- π§ Partial Class Requirement: Simple
partialkeyword enables seamless extension method generation
using Atc.SourceGenerators.Annotations;
using System.ComponentModel.DataAnnotations;
// Automatic section name inference
[OptionsBinding] // Binds to "DatabaseOptions" section (uses full class name)
public partial class DatabaseOptions
{
public string ConnectionString { get; set; }
}
// Using const SectionName (2nd priority)
[OptionsBinding(ValidateDataAnnotations = true)]
public partial class CacheOptions
{
public const string SectionName = "ApplicationCache"; // Binds to "ApplicationCache"
[Range(1, 1000)]
public int MaxSize { get; set; }
}
// Using const Name (4th priority)
[OptionsBinding]
public partial class EmailOptions
{
public const string Name = "EmailConfiguration"; // Binds to "EmailConfiguration"
public string SmtpServer { get; set; }
}
// Full priority demonstration
[OptionsBinding]
public partial class LoggingOptions
{
public const string SectionName = "X1"; // 2nd prio - WINS
public const string NameTitle = "X2"; // 3rd prio
public const string Name = "X3"; // 4th prio
// Binds to "X1"
}
// Explicit section path (1st priority - highest)
[OptionsBinding("App:Email:Smtp")]
public partial class SmtpOptions
{
public string Host { get; set; }
public int Port { get; set; }
}
// Specify lifetime for different injection patterns
[OptionsBinding("Features", Lifetime = OptionsLifetime.Monitor)]
public partial class FeatureOptions
{
public bool EnableNewFeature { get; set; }
}
// Configuration change callbacks - auto-generated IHostedService
[OptionsBinding("Features", Lifetime = OptionsLifetime.Monitor, OnChange = nameof(OnFeaturesChanged))]
public partial class FeaturesOptions
{
public bool EnableNewUI { get; set; }
public bool EnableBetaFeatures { get; set; }
// Called automatically when configuration changes (requires reloadOnChange: true)
internal static void OnFeaturesChanged(FeaturesOptions options, string? name)
{
Console.WriteLine($"[OnChange] EnableNewUI: {options.EnableNewUI}");
Console.WriteLine($"[OnChange] EnableBetaFeatures: {options.EnableBetaFeatures}");
}
}
// Usage in your services:
public class MyService
{
public MyService(IOptions<DatabaseOptions> db) // Singleton
public MyService(IOptionsSnapshot<SmtpOptions> smtp) // Scoped (reloads per request)
public MyService(IOptionsMonitor<FeatureOptions> features) // Monitor (change notifications)
}| ID | Description |
|---|---|
| ATCOPT001 | Options class must be declared as partial |
| ATCOPT002 | Section name cannot be null or empty |
| ATCOPT003 | Invalid options binding configuration |
| ATCOPT004 | OnChange requires Monitor lifetime |
| ATCOPT005 | OnChange not supported with named options |
| ATCOPT006 | OnChange callback method not found |
| ATCOPT007 | OnChange callback has invalid signature |
| ATCOPT008 | PostConfigure not supported with named options |
| ATCOPT009 | PostConfigure callback method not found |
| ATCOPT010 | PostConfigure callback has invalid signature |
Eliminate tedious object-to-object mapping code. Decorate your classes with [MapTo(typeof(TargetType))] and let the generator create type-safe mapping extension methods automatically.
- Object Mapping Guide - Full documentation with examples
- Quick Start - UserApp 3-layer architecture tutorial
- Advanced Scenarios - Enums, nested objects, multi-layer mapping
- Sample Projects - Working code examples with DataAccess β Domain β API
// Manual mapping - tedious, repetitive, error-prone π«
public UserDto MapToDto(User user)
{
return new UserDto
{
Id = user.Id,
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email,
Status = (UserStatusDto)user.Status,
Address = user.Address != null ? new AddressDto
{
Street = user.Address.Street,
City = user.Address.City,
State = user.Address.State,
PostalCode = user.Address.PostalCode,
Country = user.Address.Country
} : null,
CreatedAt = user.CreatedAt,
UpdatedAt = user.UpdatedAt
};
}
// ... repeat for every type
// ... across every layer
// ... easy to forget properties// Your domain models - Clean, declarative, self-documenting β¨
using Atc.SourceGenerators.Annotations;
[MapTo(typeof(UserDto))]
public partial class User
{
public Guid Id { get; init; }
public string FirstName { get; init; } = string.Empty;
public string LastName { get; init; } = string.Empty;
public string Email { get; init; } = string.Empty;
public UserStatus Status { get; init; }
public Address? Address { get; init; }
public DateTimeOffset CreatedAt { get; init; }
public DateTimeOffset? UpdatedAt { get; init; }
}
[MapTo(typeof(AddressDto))]
public partial class Address
{
public string Street { get; init; } = string.Empty;
public string City { get; init; } = string.Empty;
public string State { get; init; } = string.Empty;
public string PostalCode { get; init; } = string.Empty;
public string Country { get; init; } = string.Empty;
}
// Usage - One line per mapping
using Atc.Mapping;
var dto = user.MapToUserDto();
var dtos = users.Select(u => u.MapToUserDto()).ToList();- π¦ Collection Mapping: Automatic mapping for
List<T>,IEnumerable<T>, arrays, and other collection types - ποΈ Constructor Mapping: Automatically detects and uses constructors for records and classes with primary constructors (C# 12+)
- π« Property Exclusion: Use
[MapIgnore]to exclude sensitive or internal properties (works on both source and target) - π·οΈ Custom Property Names: Use
[MapProperty]to map properties with different names between source and target - π Property Flattening: Opt-in flattening support (e.g.,
Address.CityβAddressCity) - π Built-in Type Conversion: DateTime β string, Guid β string, numeric β string conversions
- β Required Property Validation: Compile-time diagnostics (ATCMAP004) for missing required properties (C# 11+)
- π³ Polymorphic/Derived Type Mapping: Runtime type discrimination using switch expressions and
[MapDerivedType] - πͺ Before/After Mapping Hooks: Custom pre/post-processing logic with
BeforeMapandAfterMapmethods - π Object Factories: Custom object creation via factory methods instead of
new TargetType() - β»οΈ Update Existing Target: Map to existing instances (EF Core tracked entities) with
UpdateTarget = true - π IQueryable Projections: EF Core server-side query optimization with
GenerateProjection = true - π· Generic Mappers: Type-safe mapping for generic wrapper types like
Result<T>andPagedResult<T> - π Private Member Access: Map to/from private and internal properties using UnsafeAccessor (.NET 8+)
- π€ Property Name Casing Strategies: CamelCase and snake_case support with
PropertyNameStrategy - 𧬠Base Class Property Inheritance: Automatically include properties from base classes (Entity audit fields, etc.)
- π Bidirectional Mapping: Generate both forward and reverse mappings with
Bidirectional = true - π Smart Enum Conversion: Uses safe EnumMapping extension methods when enums have
[MapTo]attributes, falls back to casts - πͺ Nested Object Mapping: Automatically chains mappings for nested properties
- ποΈ Multi-Layer Support: Build Entity β Domain β DTO mapping chains effortlessly
- β‘ Zero Runtime Cost: All code generated at compile time
- π Native AOT Compatible: No reflection or runtime code generation - fully trimming-safe
- π‘οΈ Type-Safe: Compile-time validation catches mapping errors before runtime
- π¦ Null Safety: Built-in null checking for nullable reference types
- π― Convention-Based: Maps properties by name - no configuration needed
using Atc.SourceGenerators.Annotations;
using Atc.Mapping;
// Source with nested object and enum
[MapTo(typeof(PersonDto))]
public partial class Person
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public Status Status { get; set; }
public Address? Address { get; set; }
}
[MapTo(typeof(AddressDto))]
public partial class Address
{
public string Street { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
}
public enum Status { Active = 0, Inactive = 1 }
// Target types
public class PersonDto
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public StatusDto Status { get; set; }
public AddressDto? Address { get; set; }
}
public class AddressDto
{
public string Street { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
}
public enum StatusDto { Active = 0, Inactive = 1 }
// β¨ Use generated extension methods
var person = new Person
{
Id = 1,
Name = "John Doe",
Status = Status.Active,
Address = new Address { Street = "123 Main St", City = "NYC" }
};
var dto = person.MapToPersonDto();
// β¨ Automatic enum conversion
// β¨ Automatic nested object mapping (Address β AddressDto)
// β¨ Null safety built-inPerfect for 3-layer architectures:
Database (Entities) β Domain (Models) β API (DTOs)
// Data Access Layer
[MapTo(typeof(Domain.Product))]
public partial class ProductEntity
{
public int DatabaseId { get; set; }
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public bool IsDeleted { get; set; } // DB-specific field
}
// Domain Layer
namespace Domain;
[MapTo(typeof(ProductDto))]
public partial class Product
{
public Guid Id { get; init; }
public string Name { get; init; } = string.Empty;
public decimal Price { get; init; }
}
public class ProductDto
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
}
// β¨ Complete mapping chain
var entity = repository.GetById(1);
var domain = entity.MapToProduct();
var dto = domain.MapToProductDto();Get errors at compile time, not runtime:
| ID | Description |
|---|---|
| ATCMAP001 | Mapping class must be declared as partial |
| ATCMAP002 | Target type must be a class or struct |
Eliminate manual enum conversions with intelligent enum-to-enum mapping. Decorate your enums with [MapTo(typeof(TargetEnum))] and let the generator create type-safe switch expression mappings with special case handling automatically.
- Enum Mapping Guide - Full documentation with examples
- Quick Start - PetStore enum mapping tutorial
- Special Case Mappings - None β Unknown, Active β Enabled, etc.
- Sample Projects - Working code examples with bidirectional mapping
// Manual enum mapping - tedious, error-prone, inflexible π«
public PetStatusDto MapToDto(PetStatusEntity status)
{
return status switch
{
PetStatusEntity.None => PetStatusDto.Unknown,
PetStatusEntity.Pending => PetStatusDto.Pending,
PetStatusEntity.Available => PetStatusDto.Available,
PetStatusEntity.Adopted => PetStatusDto.Adopted,
_ => throw new ArgumentOutOfRangeException(nameof(status)),
};
}
public PetStatusEntity MapToEntity(PetStatusDto status)
{
return status switch
{
PetStatusDto.Unknown => PetStatusEntity.None,
PetStatusDto.Pending => PetStatusEntity.Pending,
PetStatusDto.Available => PetStatusEntity.Available,
PetStatusDto.Adopted => PetStatusEntity.Adopted,
_ => throw new ArgumentOutOfRangeException(nameof(status)),
};
}
// ... repeat for every enum pair
// ... across every layer
// ... easy to make mistakes// Your enums - Clean, declarative, self-documenting β¨
using Atc.SourceGenerators.Annotations;
// Database layer
[MapTo(typeof(PetStatusDto), Bidirectional = true)]
public enum PetStatusEntity
{
None, // β¨ Auto-maps to PetStatusDto.Unknown (special case)
Pending,
Available,
Adopted,
}
// API layer
public enum PetStatusDto
{
Unknown, // β¨ Auto-maps from PetStatusEntity.None
Available,
Pending,
Adopted,
}
// Usage - Generated extension methods
using Atc.Mapping;
var entity = PetStatusEntity.None;
var dto = entity.MapToPetStatusDto(); // PetStatusDto.Unknown
var back = dto.MapToPetStatusEntity(); // PetStatusEntity.None (bidirectional!)- π― Intelligent Name Matching: Maps enum values by name with case-insensitive support
- π Special Case Detection: Automatically handles "zero/empty/null" state equivalents:
NoneβUnknown,DefaultUnknownβNone,DefaultDefaultβNone,Unknown
- π Bidirectional Mapping: Generate both forward and reverse mappings with
Bidirectional = true - π€ Case-Insensitive: Matches enum values regardless of casing differences
- β‘ Zero Runtime Cost: Pure switch expressions, no reflection or runtime code generation
- π‘οΈ Type-Safe: Compile-time validation with diagnostics (ATCENUM002) for unmapped values
- π Native AOT Compatible: Fully trimming-safe, works with Native AOT
β οΈ Runtime Safety:ArgumentOutOfRangeExceptionthrown for unmapped values
using Atc.SourceGenerators.Annotations;
using Atc.Mapping;
// Database layer enum with special case mapping
[MapTo(typeof(StatusDto), Bidirectional = true)]
public enum StatusEntity
{
None, // β¨ Maps to StatusDto.Unknown (special case)
Active, // β¨ Exact name match
Inactive, // β¨ Exact name match
}
public enum StatusDto
{
Unknown, // β¨ Maps from StatusEntity.None (special case)
Active, // β¨ Exact name match
Inactive, // β¨ Exact name match
}
// β¨ Use generated extension methods
var entity = StatusEntity.None;
var dto = entity.MapToStatusDto(); // StatusDto.Unknown
var back = dto.MapToStatusEntity(); // StatusEntity.None (bidirectional!)Get errors and warnings at compile time, not runtime:
| ID | Description |
|---|---|
| ATCENUM001 | Target type must be an enum |
| ATCENUM002 | Enum value has no matching target value (Warning) |
dotnet builddotnet testWorking code examples demonstrating each generator in realistic scenarios:
Multi-project console app showing automatic DI registration across layers with auto-detection of interfaces.
cd sample/Atc.SourceGenerators.DependencyRegistration
dotnet runβοΈ OptionsBinding Sample
Console app demonstrating type-safe configuration binding with validation and multiple options classes.
cd sample/Atc.SourceGenerators.OptionsBinding
dotnet runπΊοΈ Mapping Sample
ASP.NET Core Minimal API showing 3-layer mapping (Entity β Domain β DTO) with automatic enum conversion and nested objects.
cd sample/Atc.SourceGenerators.Mapping
dotnet runπ EnumMapping Sample
Console app demonstrating intelligent enum-to-enum mapping with special case handling (None β Unknown, Active β Enabled), bidirectional mappings, and case-insensitive matching.
cd sample/Atc.SourceGenerators.EnumMapping
dotnet runFull-featured ASP.NET Core application using all four generators together with OpenAPI/Scalar documentation. This demonstrates production-ready patterns for modern .NET applications.
cd sample/PetStore.Api
dotnet run
# Open https://localhost:42616/scalar/v1 for API documentationContributions are welcome! Please feel free to submit a Pull Request.
[License information here]