-- **Sample Projects**: See `/sample/Atc.SourceGenerators.AnnotationConstants`
-
----
-
-**Last Updated**: 2025-12-19
-**Version**: 1.0 (Implemented)
-**Maintained By**: Atc.SourceGenerators Team
diff --git a/docs/AnnotationConstantsGenerator-Samples.md b/docs/AnnotationConstantsGenerator-Samples.md
deleted file mode 100644
index f012d32..0000000
--- a/docs/AnnotationConstantsGenerator-Samples.md
+++ /dev/null
@@ -1,569 +0,0 @@
-# 🎯 Annotation Constants Generator - Sample Projects
-
-This document provides working examples demonstrating the **AnnotationConstantsGenerator** in realistic scenarios.
-
-## 📁 Sample Project Location
-
-```
-sample/
-└── Atc.SourceGenerators.AnnotationConstants/
- ├── Atc.SourceGenerators.AnnotationConstants.csproj
- ├── Models/
- │ ├── Product.cs
- │ └── Customer.cs
- └── Program.cs
-```
-
-## 🚀 Running the Sample
-
-```bash
-cd sample/Atc.SourceGenerators.AnnotationConstants
-dotnet run
-```
-
-**Expected Output:**
-
-```bash
-=== Annotation Constants Generator Demo ===
-
-Product.Name:
- DisplayName: Product Name
- MaximumLength: 100
- MinimumLength: 3
- IsRequired: true
-
-Product.Price:
- DisplayName: Price
- Minimum: 0.01
- Maximum: 999999.99
- OperandType: System.Decimal
- IsRequired: true
-
-Product.Sku:
- DisplayName: SKU
- MaximumLength: 20
- Pattern: ^[A-Z]{3}-\d{4}$
- IsRequired: false
-
-Customer.Email:
- DisplayName: Email Address
- IsRequired: true
- IsEmailAddress: true
-
-Customer.Phone:
- DisplayName: Phone Number
- IsPhone: true
-```
-
----
-
-## 📋 Sample Code
-
-### Models/Product.cs
-
-```csharp
-using System.ComponentModel.DataAnnotations;
-
-namespace Atc.SourceGenerators.Sample.Models;
-
-///
-/// Demonstrates DataAnnotation extraction for a product entity.
-///
-public class Product
-{
- ///
- /// Product name with display metadata and validation constraints.
- ///
- [Display(Name = "Product Name", Description = "The display name of the product")]
- [Required(ErrorMessage = "Product name is required")]
- [StringLength(100, MinimumLength = 3, ErrorMessage = "Name must be 3-100 characters")]
- public string Name { get; set; } = string.Empty;
-
- ///
- /// Product price with Range validation using decimal type.
- ///
- [Display(Name = "Price", Description = "The retail price of the product")]
- [Required]
- [Range(typeof(decimal), "0.01", "999999.99", ErrorMessage = "Price must be between $0.01 and $999,999.99")]
- public decimal Price { get; set; }
-
- ///
- /// Stock Keeping Unit with regex pattern validation.
- ///
- [Display(Name = "SKU", ShortName = "SKU", Description = "Stock Keeping Unit identifier")]
- [StringLength(20)]
- [RegularExpression(@"^[A-Z]{3}-\d{4}$", ErrorMessage = "SKU must be in format AAA-0000")]
- public string? Sku { get; set; }
-
- ///
- /// Product quantity with integer Range validation.
- ///
- [Display(Name = "Quantity in Stock")]
- [Range(0, 10000)]
- public int Quantity { get; set; }
-
- ///
- /// Product category with display grouping.
- ///
- [Display(Name = "Category", GroupName = "Classification")]
- [Required]
- public string Category { get; set; } = string.Empty;
-
- ///
- /// Internal notes - not editable via forms.
- ///
- [Display(Name = "Internal Notes")]
- [Editable(false)]
- [ScaffoldColumn(false)]
- public string? InternalNotes { get; set; }
-}
-```
-
-### Models/Customer.cs
-
-```csharp
-using System.ComponentModel.DataAnnotations;
-
-namespace Atc.SourceGenerators.Sample.Models;
-
-///
-/// Demonstrates DataAnnotation extraction for a customer entity.
-///
-public class Customer
-{
- ///
- /// Primary key identifier.
- ///
- [Key]
- public Guid Id { get; set; }
-
- ///
- /// Customer's full name.
- ///
- [Display(Name = "Full Name", Prompt = "Enter customer's full name")]
- [Required(ErrorMessage = "Name is required")]
- [StringLength(150, MinimumLength = 2)]
- public string Name { get; set; } = string.Empty;
-
- ///
- /// Email address with specialized validation.
- ///
- [Display(Name = "Email Address", Description = "Primary contact email")]
- [Required]
- [EmailAddress(ErrorMessage = "Invalid email format")]
- public string Email { get; set; } = string.Empty;
-
- ///
- /// Email confirmation for registration.
- ///
- [Display(Name = "Confirm Email")]
- [Compare(nameof(Email), ErrorMessage = "Emails must match")]
- public string ConfirmEmail { get; set; } = string.Empty;
-
- ///
- /// Phone number with specialized validation.
- ///
- [Display(Name = "Phone Number")]
- [Phone]
- public string? Phone { get; set; }
-
- ///
- /// Customer website URL.
- ///
- [Display(Name = "Website")]
- [Url]
- public string? Website { get; set; }
-
- ///
- /// Credit card for payment.
- ///
- [Display(Name = "Credit Card")]
- [CreditCard]
- public string? CreditCard { get; set; }
-
- ///
- /// Customer age with range validation.
- ///
- [Display(Name = "Age")]
- [Range(18, 120, ErrorMessage = "Age must be between 18 and 120")]
- public int? Age { get; set; }
-
- ///
- /// Account creation timestamp.
- ///
- [Display(Name = "Created At")]
- [Editable(false)]
- [DataType(DataType.DateTime)]
- public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
-
- ///
- /// Optimistic concurrency token.
- ///
- [Timestamp]
- public byte[]? RowVersion { get; set; }
-}
-```
-
-### Program.cs
-
-```csharp
-using Atc.SourceGenerators.Sample.Models;
-
-Console.WriteLine("=== Annotation Constants Generator Demo ===");
-Console.WriteLine();
-
-// ===== Product Annotations =====
-Console.WriteLine("Product.Name:");
-Console.WriteLine($" DisplayName: {AnnotationConstants.Product.Name.DisplayName}");
-Console.WriteLine($" Description: {AnnotationConstants.Product.Name.Description}");
-Console.WriteLine($" MaximumLength: {AnnotationConstants.Product.Name.MaximumLength}");
-Console.WriteLine($" MinimumLength: {AnnotationConstants.Product.Name.MinimumLength}");
-Console.WriteLine($" IsRequired: {AnnotationConstants.Product.Name.IsRequired}");
-Console.WriteLine($" ErrorMessage: {AnnotationConstants.Product.Name.StringLengthErrorMessage}");
-Console.WriteLine();
-
-Console.WriteLine("Product.Price:");
-Console.WriteLine($" DisplayName: {AnnotationConstants.Product.Price.DisplayName}");
-Console.WriteLine($" Minimum: {AnnotationConstants.Product.Price.Minimum}");
-Console.WriteLine($" Maximum: {AnnotationConstants.Product.Price.Maximum}");
-Console.WriteLine($" OperandType: {AnnotationConstants.Product.Price.OperandType}");
-Console.WriteLine($" IsRequired: {AnnotationConstants.Product.Price.IsRequired}");
-Console.WriteLine();
-
-Console.WriteLine("Product.Sku:");
-Console.WriteLine($" DisplayName: {AnnotationConstants.Product.Sku.DisplayName}");
-Console.WriteLine($" ShortName: {AnnotationConstants.Product.Sku.ShortName}");
-Console.WriteLine($" MaximumLength: {AnnotationConstants.Product.Sku.MaximumLength}");
-Console.WriteLine($" Pattern: {AnnotationConstants.Product.Sku.Pattern}");
-Console.WriteLine();
-
-Console.WriteLine("Product.Quantity:");
-Console.WriteLine($" DisplayName: {AnnotationConstants.Product.Quantity.DisplayName}");
-Console.WriteLine($" Minimum: {AnnotationConstants.Product.Quantity.Minimum}");
-Console.WriteLine($" Maximum: {AnnotationConstants.Product.Quantity.Maximum}");
-Console.WriteLine();
-
-Console.WriteLine("Product.InternalNotes:");
-Console.WriteLine($" DisplayName: {AnnotationConstants.Product.InternalNotes.DisplayName}");
-Console.WriteLine($" IsEditable: {AnnotationConstants.Product.InternalNotes.IsEditable}");
-Console.WriteLine($" IsScaffoldColumn: {AnnotationConstants.Product.InternalNotes.IsScaffoldColumn}");
-Console.WriteLine();
-
-// ===== Customer Annotations =====
-Console.WriteLine("Customer.Id:");
-Console.WriteLine($" IsKey: {AnnotationConstants.Customer.Id.IsKey}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.Name:");
-Console.WriteLine($" DisplayName: {AnnotationConstants.Customer.Name.DisplayName}");
-Console.WriteLine($" Prompt: {AnnotationConstants.Customer.Name.Prompt}");
-Console.WriteLine($" IsRequired: {AnnotationConstants.Customer.Name.IsRequired}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.Email:");
-Console.WriteLine($" DisplayName: {AnnotationConstants.Customer.Email.DisplayName}");
-Console.WriteLine($" IsRequired: {AnnotationConstants.Customer.Email.IsRequired}");
-Console.WriteLine($" IsEmailAddress: {AnnotationConstants.Customer.Email.IsEmailAddress}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.ConfirmEmail:");
-Console.WriteLine($" CompareProperty: {AnnotationConstants.Customer.ConfirmEmail.CompareProperty}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.Phone:");
-Console.WriteLine($" DisplayName: {AnnotationConstants.Customer.Phone.DisplayName}");
-Console.WriteLine($" IsPhone: {AnnotationConstants.Customer.Phone.IsPhone}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.Website:");
-Console.WriteLine($" IsUrl: {AnnotationConstants.Customer.Website.IsUrl}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.CreditCard:");
-Console.WriteLine($" IsCreditCard: {AnnotationConstants.Customer.CreditCard.IsCreditCard}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.Age:");
-Console.WriteLine($" Minimum: {AnnotationConstants.Customer.Age.Minimum}");
-Console.WriteLine($" Maximum: {AnnotationConstants.Customer.Age.Maximum}");
-Console.WriteLine($" RangeErrorMessage: {AnnotationConstants.Customer.Age.RangeErrorMessage}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.CreatedAt:");
-Console.WriteLine($" IsEditable: {AnnotationConstants.Customer.CreatedAt.IsEditable}");
-Console.WriteLine($" DataType: {AnnotationConstants.Customer.CreatedAt.DataType}");
-Console.WriteLine();
-
-Console.WriteLine("Customer.RowVersion:");
-Console.WriteLine($" IsTimestamp: {AnnotationConstants.Customer.RowVersion.IsTimestamp}");
-Console.WriteLine();
-
-// ===== Practical Usage Examples =====
-Console.WriteLine("=== Practical Usage Examples ===");
-Console.WriteLine();
-
-// Example 1: Client-side validation rules
-Console.WriteLine("1. Generate JavaScript Validation Rules:");
-Console.WriteLine($$"""
- const productValidation = {
- name: {
- required: {{AnnotationConstants.Product.Name.IsRequired.ToString().ToLowerInvariant()}},
- maxLength: {{AnnotationConstants.Product.Name.MaximumLength}},
- minLength: {{AnnotationConstants.Product.Name.MinimumLength}}
- },
- price: {
- required: {{AnnotationConstants.Product.Price.IsRequired.ToString().ToLowerInvariant()}},
- min: {{AnnotationConstants.Product.Price.Minimum}},
- max: {{AnnotationConstants.Product.Price.Maximum}}
- },
- sku: {
- pattern: '{{AnnotationConstants.Product.Sku.Pattern}}'
- }
- };
- """);
-Console.WriteLine();
-
-// Example 2: Form field generation
-Console.WriteLine("2. Generate Form Fields:");
-GenerateFormField("Name", AnnotationConstants.Product.Name.DisplayName,
- AnnotationConstants.Product.Name.Description,
- AnnotationConstants.Product.Name.MaximumLength,
- AnnotationConstants.Product.Name.IsRequired);
-Console.WriteLine();
-
-// Example 3: API documentation
-Console.WriteLine("3. Generate API Documentation:");
-Console.WriteLine($$"""
- ## POST /api/products
-
- | Field | Description | Required | Constraints |
- |-------|-------------|----------|-------------|
- | name | {{AnnotationConstants.Product.Name.Description}} | {{AnnotationConstants.Product.Name.IsRequired}} | {{AnnotationConstants.Product.Name.MinimumLength}}-{{AnnotationConstants.Product.Name.MaximumLength}} chars |
- | price | {{AnnotationConstants.Product.Price.Description}} | {{AnnotationConstants.Product.Price.IsRequired}} | ${{AnnotationConstants.Product.Price.Minimum}}-${{AnnotationConstants.Product.Price.Maximum}} |
- | sku | {{AnnotationConstants.Product.Sku.Description}} | No | Pattern: {{AnnotationConstants.Product.Sku.Pattern}} |
- """);
-
-static void GenerateFormField(string fieldName, string displayName, string? description, int maxLength, bool required)
-{
- var requiredAttr = required ? " required" : "";
- Console.WriteLine($$"""
-
-
-
- {{(description != null ? $"{description}" : "")}}
-
- """);
-}
-```
-
----
-
-## 🏗️ Project Structure
-
-### Generated Code Structure
-
-When you build the sample project, the generator creates:
-
-```bash
-obj/
-└── Debug/
- └── net10.0/
- └── generated/
- └── Atc.SourceGenerators/
- └── Atc.SourceGenerators.AnnotationConstantsGenerator/
- ├── AnnotationConstants.Atc.SourceGenerators.Sample.Models.Product.g.cs
- └── AnnotationConstants.Atc.SourceGenerators.Sample.Models.Customer.g.cs
-```
-
-### Generated File Example
-
-**AnnotationConstants.Atc.SourceGenerators.Sample.Models.Product.g.cs:**
-
-```csharp
-//
-#nullable enable
-
-namespace Atc.SourceGenerators.Sample.Models;
-
-///
-/// Annotation constants for types in Atc.SourceGenerators.Sample.Models.
-///
-[global::System.CodeDom.Compiler.GeneratedCode("Atc.SourceGenerators.AnnotationConstants", "1.0.0")]
-[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
-[global::System.Runtime.CompilerServices.CompilerGenerated]
-[global::System.Diagnostics.DebuggerNonUserCode]
-[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
-public static partial class AnnotationConstants
-{
- public static partial class Product
- {
- public static partial class Name
- {
- public const string DisplayName = "Product Name";
- public const string Description = "The display name of the product";
- public const int MinimumLength = 3;
- public const int MaximumLength = 100;
- public const bool IsRequired = true;
- public const string RequiredErrorMessage = "Product name is required";
- public const string StringLengthErrorMessage = "Name must be 3-100 characters";
- }
-
- public static partial class Price
- {
- public const string DisplayName = "Price";
- public const string Description = "The retail price of the product";
- public const string Minimum = "0.01";
- public const string Maximum = "999999.99";
- public static readonly global::System.Type OperandType = typeof(decimal);
- public const bool IsRequired = true;
- public const string RangeErrorMessage = "Price must be between $0.01 and $999,999.99";
- }
-
- public static partial class Sku
- {
- public const string DisplayName = "SKU";
- public const string ShortName = "SKU";
- public const string Description = "Stock Keeping Unit identifier";
- public const int MaximumLength = 20;
- public const string Pattern = @"^[A-Z]{3}-\d{4}$";
- public const string RegularExpressionErrorMessage = "SKU must be in format AAA-0000";
- }
-
- public static partial class Quantity
- {
- public const string DisplayName = "Quantity in Stock";
- public const string Minimum = "0";
- public const string Maximum = "10000";
- public static readonly global::System.Type OperandType = typeof(int);
- }
-
- public static partial class Category
- {
- public const string DisplayName = "Category";
- public const string GroupName = "Classification";
- public const bool IsRequired = true;
- }
-
- public static partial class InternalNotes
- {
- public const string DisplayName = "Internal Notes";
- public const bool IsEditable = false;
- public const bool IsScaffoldColumn = false;
- }
- }
-}
-```
-
----
-
-## 🎨 Real-World Use Cases
-
-### Use Case 1: Blazor Form Generation
-
-```razor
-@* FormField.razor - Generic form field component *@
-@typeparam TModel
-
-
-
-
-
-
- @if (!string.IsNullOrEmpty(Description))
- {
- @Description
- }
-
-
-
-
-@code {
- [Parameter] public string FieldName { get; set; } = string.Empty;
- [Parameter] public string DisplayName { get; set; } = string.Empty;
- [Parameter] public string? Description { get; set; }
- [Parameter] public string? Prompt { get; set; }
- [Parameter] public int MaxLength { get; set; } = 255;
- [Parameter] public bool Required { get; set; }
- [Parameter] public string Value { get; set; } = string.Empty;
- [Parameter] public EventCallback ValueChanged { get; set; }
-}
-```
-
-**Usage with generated constants:**
-
-```razor
-
-```
-
-### Use Case 2: Minimal API Documentation
-
-```csharp
-app.MapPost("/api/products", async (Product product, AppDbContext db) =>
-{
- db.Products.Add(product);
- await db.SaveChangesAsync();
- return Results.Created($"/api/products/{product.Id}", product);
-})
-.WithName("CreateProduct")
-.WithOpenApi(operation =>
-{
- operation.Description = "Creates a new product";
- operation.Parameters[0].Description =
- $"{AnnotationConstants.Product.Name.DisplayName}: " +
- $"{AnnotationConstants.Product.Name.MinimumLength}-{AnnotationConstants.Product.Name.MaximumLength} characters, " +
- $"Required: {AnnotationConstants.Product.Name.IsRequired}";
- return operation;
-});
-```
-
-### Use Case 3: TypeScript Type Generation
-
-```csharp
-// Generate TypeScript interfaces with validation metadata
-var tsGenerator = new TypeScriptGenerator();
-
-tsGenerator.AddType("Product", new Dictionary
-{
- ["name"] = new(
- DisplayName: AnnotationConstants.Product.Name.DisplayName,
- Required: AnnotationConstants.Product.Name.IsRequired,
- MaxLength: AnnotationConstants.Product.Name.MaximumLength,
- MinLength: AnnotationConstants.Product.Name.MinimumLength
- ),
- ["price"] = new(
- DisplayName: AnnotationConstants.Product.Price.DisplayName,
- Required: AnnotationConstants.Product.Price.IsRequired,
- Min: decimal.Parse(AnnotationConstants.Product.Price.Minimum),
- Max: decimal.Parse(AnnotationConstants.Product.Price.Maximum)
- ),
- ["sku"] = new(
- DisplayName: AnnotationConstants.Product.Sku.DisplayName,
- Pattern: AnnotationConstants.Product.Sku.Pattern
- )
-});
-
-var typescript = tsGenerator.Generate();
-// Output:
-// interface Product {
-// name: string; // Product Name, required, 3-100 chars
-// price: number; // Price, required, 0.01-999999.99
-// sku?: string; // SKU, pattern: ^[A-Z]{3}-\d{4}$
-// }
-```
-
----
-
-## 🔗 Related Documentation
-
-- [Main Documentation](AnnotationConstantsGenerator.md)
-- [Feature Roadmap](AnnotationConstantsGenerator-FeatureRoadmap.md)
diff --git a/docs/AnnotationConstantsGenerator.md b/docs/AnnotationConstantsGenerator.md
deleted file mode 100644
index 5d0741d..0000000
--- a/docs/AnnotationConstantsGenerator.md
+++ /dev/null
@@ -1,439 +0,0 @@
-# 📝 Annotation Constants Source Generator
-
-Automatically extract DataAnnotation metadata from class/record properties and generate compile-time accessible constants without reflection.
-
-**Key Benefits:**
-
-- 🎯 **Zero reflection** - Access annotation values at compile time
-- ⚡ **Native AOT ready** - Works with trimming and ahead-of-time compilation
-- 🛡️ **Type-safe constants** - Strongly-typed int, string, and bool values
-- 🔍 **Discoverable** - Full IntelliSense support via nested class structure
-- 🚀 **Zero configuration** - Works out of the box, no opt-in attribute needed
-
-**Quick Example:**
-
-```csharp
-// Input: Class with DataAnnotation attributes
-public class Product
-{
- [Display(Name = "Product Name")]
- [Required]
- [StringLength(100)]
- public string Name { get; set; } = string.Empty;
-
- [Display(Name = "Price")]
- [Range(typeof(decimal), "0.01", "999999.99")]
- public decimal Price { get; set; }
-}
-
-// Generated: Compile-time constants
-string label = AnnotationConstants.Product.Name.DisplayName; // "Product Name"
-int maxLength = AnnotationConstants.Product.Name.MaximumLength; // 100
-bool required = AnnotationConstants.Product.Name.IsRequired; // true
-
-string minPrice = AnnotationConstants.Product.Price.Minimum; // "0.01"
-string maxPrice = AnnotationConstants.Product.Price.Maximum; // "999999.99"
-```
-
-## 📖 Documentation Navigation
-
-- **[📋 Feature Roadmap](AnnotationConstantsGenerator-FeatureRoadmap.md)** - See all implemented and planned features
-- **[🎯 Sample Projects](AnnotationConstantsGenerator-Samples.md)** - Working code examples
-
-> **Note:** This generator supports both **Microsoft DataAnnotations** and **Atc attributes**. When the Atc package is referenced, additional validation attributes (IPAddress, Uri, String, KeyString, IsoCurrencySymbol) are also extracted.
-
-## 📑 Table of Contents
-
-- [📝 Annotation Constants Source Generator](#-annotation-constants-source-generator)
- - [📖 Documentation Navigation](#-documentation-navigation)
- - [📑 Table of Contents](#-table-of-contents)
- - [📖 Overview](#-overview)
- - [😫 Before (Reflection Approach)](#-before-reflection-approach)
- - [✨ After (With Source Generator)](#-after-with-source-generator)
- - [🚀 Quick Start](#-quick-start)
- - [1. Install the Package](#1-install-the-package)
- - [2. Add DataAnnotation Attributes](#2-add-dataannotation-attributes)
- - [3. Use Generated Constants](#3-use-generated-constants)
- - [✨ Features](#-features)
- - [📦 Supported Attributes](#-supported-attributes)
- - [Display Attributes](#display-attributes)
- - [Validation Attributes](#validation-attributes)
- - [Data Type Attributes](#data-type-attributes)
- - [Metadata Attributes](#metadata-attributes)
- - [Atc Attributes (from Atc Package)](#atc-attributes-from-atc-package)
- - [💡 Usage Examples](#-usage-examples)
- - [Blazor Form Labels](#blazor-form-labels)
- - [Client-Side Validation](#client-side-validation)
- - [API Documentation](#api-documentation)
- - [🔧 Configuration](#-configuration)
- - [Include Unannotated Properties](#include-unannotated-properties)
- - [🔧 How It Works](#-how-it-works)
- - [1. Class Scanning](#1-class-scanning)
- - [2. Attribute Extraction](#2-attribute-extraction)
- - [3. Code Generation](#3-code-generation)
- - [🛡️ Compile-Time Safety](#️-compile-time-safety)
- - [🎯 Use Cases](#-use-cases)
-
-## 📖 Overview
-
-### 😫 Before (Reflection Approach)
-
-```csharp
-// Using reflection to get annotation values - slow and not AOT-compatible 😫
-var displayAttr = typeof(Product)
- .GetProperty(nameof(Product.Name))
- ?.GetCustomAttribute();
-
-string? displayName = displayAttr?.Name; // Runtime reflection call
-
-var stringLengthAttr = typeof(Product)
- .GetProperty(nameof(Product.Name))
- ?.GetCustomAttribute();
-
-int? maxLength = stringLengthAttr?.MaximumLength; // Another reflection call
-
-// Problems:
-// - Runtime overhead for every access
-// - Not compatible with Native AOT
-// - No compile-time validation
-// - Verbose and repetitive code
-```
-
-### ✨ After (With Source Generator)
-
-```csharp
-// Using generated constants - zero reflection, AOT-compatible ✨
-string displayName = AnnotationConstants.Product.Name.DisplayName; // Compile-time constant
-int maxLength = AnnotationConstants.Product.Name.MaximumLength; // Compile-time constant
-
-// Benefits:
-// - Zero runtime overhead (compile-time constants)
-// - Native AOT compatible
-// - Full IntelliSense support
-// - Type-safe (int for lengths, string for names)
-```
-
-## 🚀 Quick Start
-
-### 1. Install the Package
-
-```bash
-dotnet add package Atc.SourceGenerators
-```
-
-Or in your `.csproj`:
-
-```xml
-
-
-
-```
-
-### 2. Add DataAnnotation Attributes
-
-No special setup needed! Just use standard DataAnnotation attributes on your classes:
-
-```csharp
-using System.ComponentModel.DataAnnotations;
-
-namespace MyApp.Models;
-
-public class Customer
-{
- [Display(Name = "Customer Name", Description = "Full legal name")]
- [Required(ErrorMessage = "Name is required")]
- [StringLength(100, MinimumLength = 2)]
- public string Name { get; set; } = string.Empty;
-
- [Display(Name = "Email Address")]
- [Required]
- [EmailAddress]
- public string Email { get; set; } = string.Empty;
-
- [Display(Name = "Age")]
- [Range(18, 120)]
- public int Age { get; set; }
-}
-```
-
-### 3. Use Generated Constants
-
-The generator automatically creates a nested static class structure:
-
-```csharp
-using MyApp.Models;
-
-// Access constants without reflection
-Console.WriteLine($"Field: {AnnotationConstants.Customer.Name.DisplayName}"); // "Customer Name"
-Console.WriteLine($"Max: {AnnotationConstants.Customer.Name.MaximumLength}"); // 100
-Console.WriteLine($"Min: {AnnotationConstants.Customer.Name.MinimumLength}"); // 2
-Console.WriteLine($"Required: {AnnotationConstants.Customer.Name.IsRequired}"); // true
-
-Console.WriteLine($"Email Required: {AnnotationConstants.Customer.Email.IsRequired}"); // true
-Console.WriteLine($"Is Email: {AnnotationConstants.Customer.Email.IsEmailAddress}"); // true
-
-Console.WriteLine($"Age Min: {AnnotationConstants.Customer.Age.Minimum}"); // "18"
-Console.WriteLine($"Age Max: {AnnotationConstants.Customer.Age.Maximum}"); // "120"
-```
-
-## ✨ Features
-
-- **🔍 Automatic Scanning** - No opt-in attribute needed; scans all classes with DataAnnotation attributes
-- **📋 Display Attribute** - DisplayName, Description, ShortName, GroupName, Prompt, Order
-- **✅ Validation Attributes** - Required, StringLength, Range, MinLength, MaxLength, RegularExpression
-- **📧 Data Type Attributes** - EmailAddress, Phone, Url, CreditCard, DataType
-- **🔑 Metadata Attributes** - Key, Editable, ScaffoldColumn, Timestamp, Compare
-- **⚙️ Configurable** - Customize behavior via .editorconfig
-- **📦 Multi-Assembly** - Works across project references
-- **⚡ Zero Runtime Cost** - All constants generated at compile time
-- **🚀 Native AOT Ready** - No reflection, fully trimming-safe
-
-## 📦 Supported Attributes
-
-### Display Attributes
-
-| Attribute Property | Generated Constant | Type |
-|-----------------------|--------------------|----------|
-| `Display.Name` | `DisplayName` | `string` |
-| `Display.Description` | `Description` | `string` |
-| `Display.ShortName` | `ShortName` | `string` |
-| `Display.GroupName` | `GroupName` | `string` |
-| `Display.Prompt` | `Prompt` | `string` |
-| `Display.Order` | `Order` | `int` |
-
-### Validation Attributes
-
-| Attribute | Generated Constants | Types |
-|----------|-------------------|-------|
-| `Required` | `IsRequired`, `AllowEmptyStrings`, `RequiredErrorMessage` | `bool`, `bool`, `string` |
-| `StringLength` | `MinimumLength`, `MaximumLength`, `StringLengthErrorMessage` | `int`, `int`, `string` |
-| `Range` | `Minimum`, `Maximum`, `OperandType`, `RangeErrorMessage` | `string`, `string`, `Type`, `string` |
-| `MinLength` | `MinimumLength`, `MinLengthErrorMessage` | `int`, `string` |
-| `MaxLength` | `MaximumLength`, `MaxLengthErrorMessage` | `int`, `string` |
-| `RegularExpression` | `Pattern`, `RegularExpressionErrorMessage` | `string`, `string` |
-
-### Data Type Attributes
-
-| Attribute | Generated Constant | Type |
-|----------|-------------------|------|
-| `EmailAddress` | `IsEmailAddress` | `bool` |
-| `Phone` | `IsPhone` | `bool` |
-| `Url` | `IsUrl` | `bool` |
-| `CreditCard` | `IsCreditCard` | `bool` |
-| `DataType` | `DataType` | `int` (enum value) |
-
-### Metadata Attributes
-
-| Attribute | Generated Constant | Type |
-|----------|-------------------|------|
-| `Key` | `IsKey` | `bool` |
-| `Editable` | `IsEditable` | `bool` |
-| `ScaffoldColumn` | `IsScaffoldColumn` | `bool` |
-| `Timestamp` | `IsTimestamp` | `bool` |
-| `Compare` | `CompareProperty` | `string` |
-
-### Atc Attributes (from Atc Package)
-
-When your project references the [Atc](https://www.nuget.org/packages/Atc/) package, the generator also extracts constants from Atc-specific validation attributes:
-
-| Attribute | Generated Constants | Types |
-|----------|-------------------|-------|
-| `IPAddressAttribute` | `IsIPAddress`, `IPAddressRequired` | `bool`, `bool` |
-| `IsoCurrencySymbolAttribute` | `IsIsoCurrencySymbol`, `IsoCurrencySymbolRequired`, `AllowedIsoCurrencySymbols` | `bool`, `bool`, `string[]` |
-| `StringAttribute` | `IsAtcString`, `AtcStringRequired`, `AtcStringMinLength`, `AtcStringMaxLength`, `AtcStringRegularExpression`, `AtcStringInvalidCharacters`, `AtcStringInvalidPrefixStrings` | `bool`, `bool`, `uint`, `uint`, `string`, `char[]`, `string[]` |
-| `KeyStringAttribute` | `IsKeyString` (plus all StringAttribute constants) | `bool` |
-| `UriAttribute` | `IsAtcUri`, `AtcUriRequired`, `AtcUriAllowHttp`, `AtcUriAllowHttps`, `AtcUriAllowFtp`, `AtcUriAllowFtps`, `AtcUriAllowFile`, `AtcUriAllowOpcTcp` | all `bool` |
-| `IgnoreDisplayAttribute` | `IsIgnoreDisplay` | `bool` |
-| `EnumGuidAttribute` | `EnumGuid` | `string` |
-| `CasingStyleDescriptionAttribute` | `CasingStyleDefault`, `CasingStylePrefix` | `string`, `string` |
-
-**Example with Atc attributes:**
-
-```csharp
-// Add Atc package reference
-//
-
-public class NetworkConfig
-{
- [Display(Name = "Server IP")]
- [IPAddress(Required = true)]
- public string ServerAddress { get; set; } = string.Empty;
-
- [Display(Name = "API Endpoint")]
- [UriAttribute(Required = true, AllowHttp = false, AllowHttps = true)]
- public string ApiEndpoint { get; set; } = string.Empty;
-
- [Display(Name = "Currency")]
- [IsoCurrencySymbol(IsoCurrencySymbols = new[] { "USD", "EUR", "GBP" })]
- public string Currency { get; set; } = "USD";
-}
-
-// Access Atc constants
-bool isIPAddress = AnnotationConstants.NetworkConfig.ServerAddress.IsIPAddress; // true
-bool httpsOnly = AnnotationConstants.NetworkConfig.ApiEndpoint.AtcUriAllowHttps; // true
-string[] currencies = AnnotationConstants.NetworkConfig.Currency.AllowedIsoCurrencySymbols; // ["USD", "EUR", "GBP"]
-```
-
-## 💡 Usage Examples
-
-### Blazor Form Labels
-
-```razor
-@* Use generated constants in Blazor forms *@
-
-
-
-
- @AnnotationConstants.Customer.Name.Description
-
-
-```
-
-### Client-Side Validation
-
-```csharp
-// Generate JavaScript validation rules from constants
-var validationRules = new
-{
- name = new
- {
- required = AnnotationConstants.Customer.Name.IsRequired,
- maxLength = AnnotationConstants.Customer.Name.MaximumLength,
- minLength = AnnotationConstants.Customer.Name.MinimumLength
- },
- email = new
- {
- required = AnnotationConstants.Customer.Email.IsRequired,
- isEmail = AnnotationConstants.Customer.Email.IsEmailAddress
- }
-};
-
-// Serialize and send to JavaScript
-var json = JsonSerializer.Serialize(validationRules);
-```
-
-### API Documentation
-
-```csharp
-// Generate OpenAPI/Swagger documentation from constants
-app.MapPost("/customers", (Customer customer) => { })
- .WithDescription($"""
- Creates a new customer.
-
- Name: {AnnotationConstants.Customer.Name.Description}
- - Required: {AnnotationConstants.Customer.Name.IsRequired}
- - Max Length: {AnnotationConstants.Customer.Name.MaximumLength}
-
- Email: {AnnotationConstants.Customer.Email.DisplayName}
- - Required: {AnnotationConstants.Customer.Email.IsRequired}
- """);
-```
-
-## 🔧 Configuration
-
-The generator can be configured via `.editorconfig` or MSBuild properties.
-
-### Include Unannotated Properties
-
-By default, only properties with at least one DataAnnotation attribute are included. To include all public properties:
-
-**Option 1: .editorconfig**
-
-```ini
-[*.cs]
-atc_annotation_constants.include_unannotated_properties = true
-```
-
-**Option 2: MSBuild property**
-
-```xml
-
- true
-
-```
-
-## 🔧 How It Works
-
-### 1. Class Scanning
-
-The generator scans all classes and records in your project that have properties with DataAnnotation attributes.
-
-```csharp
-// This class will be scanned (has [Display] on Name)
-public class Product
-{
- [Display(Name = "Product Name")]
- public string Name { get; set; } = string.Empty;
-
- public string Sku { get; set; } = string.Empty; // Ignored by default
-}
-
-// This class will NOT be scanned (no DataAnnotation attributes)
-public class InternalEntity
-{
- public int Id { get; set; }
- public string Value { get; set; } = string.Empty;
-}
-```
-
-### 2. Attribute Extraction
-
-For each property with DataAnnotation attributes, the generator extracts:
-
-- Display metadata (name, description, etc.)
-- Validation rules (required, length constraints, etc.)
-- Data type hints (email, phone, etc.)
-- Entity metadata (key, editable, etc.)
-
-### 3. Code Generation
-
-The generator creates a nested static partial class hierarchy:
-
-```csharp
-// Generated in: AnnotationConstants.MyNamespace.Product.g.cs
-
-namespace MyNamespace;
-
-[global::System.CodeDom.Compiler.GeneratedCode("Atc.SourceGenerators.AnnotationConstants", "1.0.0")]
-[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
-[global::System.Runtime.CompilerServices.CompilerGenerated]
-[global::System.Diagnostics.DebuggerNonUserCode]
-[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
-public static partial class AnnotationConstants
-{
- public static partial class Product
- {
- public static partial class Name
- {
- public const string DisplayName = "Product Name";
- public const int MaximumLength = 100;
- public const bool IsRequired = true;
- }
-
- public static partial class Price
- {
- public const string DisplayName = "Price";
- public const string Minimum = "0.01";
- public const string Maximum = "999999.99";
- public static readonly System.Type OperandType = typeof(decimal);
- }
- }
-}
-```
-
-## 🎯 Use Cases
-
-1. **Blazor/MAUI Forms** - Generate form labels and validation rules without reflection
-2. **API Documentation** - Extract constraint metadata for OpenAPI/Swagger
-3. **Client-Side Validation** - Send validation rules to JavaScript/TypeScript
-4. **Code Generation** - Use constants in T4 templates or other generators
-5. **Testing** - Verify validation rules match expected values
-6. **Native AOT Applications** - Access metadata without breaking trimming
-
----
-
-**See Also:**
-
-- [Feature Roadmap](AnnotationConstantsGenerator-FeatureRoadmap.md)
-- [Sample Projects](AnnotationConstantsGenerator-Samples.md)
diff --git a/docs/DependencyRegistrationGenerators-FeatureRoadmap.md b/docs/DependencyRegistrationGenerators-FeatureRoadmap.md
deleted file mode 100644
index 00c481d..0000000
--- a/docs/DependencyRegistrationGenerators-FeatureRoadmap.md
+++ /dev/null
@@ -1,819 +0,0 @@
-# 🎯 Feature Roadmap - Dependency Registration Generator
-
-This document outlines the feature roadmap for the **DependencyRegistrationGenerator**, based on analysis of popular DI registration libraries and real-world usage patterns.
-
-## 🔍 Research Sources
-
-This roadmap is based on comprehensive analysis of:
-
-1. **Scrutor** - [khellang/Scrutor](https://github.com/khellang/Scrutor) - 4.2k⭐, 273 forks, 11.8k dependent projects
- - Runtime assembly scanning and decoration
- - Convention-based registration
- - Mature ecosystem (MIT license)
-
-2. **AutoRegisterInject** - [patrickklaeren/AutoRegisterInject](https://github.com/patrickklaeren/AutoRegisterInject) - 119⭐
- - Source generator approach with attributes
- - Per-type registration with `[RegisterScoped]`, `[RegisterSingleton]`, etc.
- - Multi-assembly support
-
-3. **Jab** - [pakrym/jab](https://github.com/pakrym/jab) - Compile-time DI container
- - 200x faster startup than Microsoft.Extensions.DependencyInjection
- - 7x faster resolution
- - AOT-friendly, zero reflection
-
-4. **Microsoft.Extensions.DependencyInjection** - Standard .NET DI abstractions
- - Keyed services (.NET 8+)
- - `IHostedService` and `BackgroundService` registration
- - Factory methods and implementation instances
-
-### 📊 Key Insights from Community
-
-**What Users Care About** (from Scrutor's 11.8k dependents):
-
-- **Convention-based registration** - Reduce boilerplate for large projects
-- **Generic interface support** - Handle `IRepository`, `IHandler`
-- **Decorator pattern** - Wrap existing registrations without modifying original code
-- **Assembly scanning** - Auto-discover services from referenced assemblies
-- **Filtering capabilities** - Exclude specific namespaces, types, or patterns
-- **Lifetime flexibility** - Different services need different lifetimes
-
-**Jab's Performance Claims**:
-
-- Compile-time generation eliminates startup overhead
-- Clean stack traces (no reflection noise)
-- Registration validation at compile time
-
-**AutoRegisterInject's Approach**:
-
-- Decentralized registration (attributes on types, not central config)
-- Reduces merge conflicts in team environments
-- Assembly-specific extension methods for modular registration
-
----
-
-## 📊 Current State
-
-### ✅ DependencyRegistrationGenerator - Implemented Features
-
-- **Auto-interface detection** - Automatically registers all implemented interfaces (excluding System.*)
-- **Explicit interface override** - Use `As` parameter to specify exact interface
-- **Register as self** - Use `As = typeof(void)` to register concrete type only
-- **Smart naming** - Generate unique extension method names (`AddDependencyRegistrationsFromDomain()`)
-- **Transitive registration** - 4 overloads support automatic or selective assembly registration
-- **Hosted service detection** - Automatically uses `AddHostedService()` for `BackgroundService` and `IHostedService`
-- **Generic interface registration** - Support open generic types like `IRepository`, `IHandler`
-- **Keyed service registration** - Multiple implementations with 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)
-- **Decorator pattern support** - Wrap services with cross-cutting concerns (logging, caching, validation)
-- **Assembly scanning filters** - Exclude types by namespace, pattern, or interface (supports wildcards)
-- **Lifetime support** - Singleton (default), Scoped, Transient
-- **Multi-project support** - Assembly-specific extension methods
-- **Compile-time validation** - Diagnostics for invalid configurations (ATCDIR001-010)
-- **Native AOT compatible** - Zero reflection, compile-time generation
-
----
-
-## 📋 Feature Status Overview
-
-| Status | Feature | Priority |
-|:------:|---------|----------|
-| ✅ | [Generic Interface Registration](#1-generic-interface-registration) | 🔴 Critical |
-| ✅ | [Keyed Service Registration](#2-keyed-service-registration) | 🔴 High |
-| ✅ | [Factory Method Registration](#3-factory-method-registration) | 🔴 High |
-| ✅ | [TryAdd* Registration](#4-tryadd-registration) | 🟡 Medium |
-| ✅ | [Assembly Scanning Filters](#5-assembly-scanning-filters) | 🟡 Medium |
-| ✅ | [Decorator Pattern Support](#6-decorator-pattern-support) | 🟢 Low-Medium |
-| ✅ | [Implementation Instance Registration](#7-implementation-instance-registration) | 🟢 Low-Medium |
-| ✅ | [Conditional Registration](#8-conditional-registration) | 🟢 Low-Medium |
-| ❌ | [Auto-Discovery by Convention](#9-auto-discovery-by-convention) | 🟢 Low |
-| ❌ | [Registration Validation Diagnostics](#10-registration-validation-diagnostics) | 🟢 Low |
-| ⚠️ | [Multi-Interface Registration](#11-multi-interface-registration-enhanced) | 🟢 Low |
-| 🚫 | [Runtime Assembly Scanning](#12-runtime-assembly-scanning) | - |
-| 🚫 | [Property/Field Injection](#13-propertyfield-injection) | - |
-| 🚫 | [Auto-Wiring Based on Reflection](#14-auto-wiring-based-on-reflection) | - |
-| 🚫 | [Service Replacement/Override at Runtime](#15-service-replacementoverride-at-runtime) | - |
-
-**Legend:**
-
-- ✅ **Implemented** - Feature is complete and available
-- ⚠️ **Partially Implemented** - Some aspects are available, others are in progress
-- ❌ **Not Implemented** - Feature is planned but not yet developed
-- 🚫 **Not Planned** - Feature is out of scope or not aligned with project goals
-
----
-
-## 🎯 Need to Have (High Priority)
-
-These features are essential based on Scrutor's popularity and real-world DI patterns.
-
-### 1. Generic Interface Registration
-
-**Priority**: 🔴 **Critical**
-**Status**: ✅ **Implemented** (v1.1)
-**Inspiration**: Scrutor's generic type support
-
-**Description**: Support registering services that implement open generic interfaces like `IRepository`, `IHandler`.
-
-**User Story**:
-> "As a developer using the repository pattern, I want to register `IRepository` implementations without manually registering each entity type."
-
-**Example**:
-
-```csharp
-// Generic interface
-public interface IRepository where T : class
-{
- Task GetByIdAsync(int id);
- Task SaveAsync(T entity);
-}
-
-// Generic implementation
-[Registration(Lifetime = Lifetime.Scoped)]
-public class Repository : IRepository where T : class
-{
- private readonly DbContext _context;
-
- public Repository(DbContext context) => _context = context;
-
- public Task GetByIdAsync(int id) => _context.Set().FindAsync(id).AsTask();
- public Task SaveAsync(T entity) { /* ... */ }
-}
-
-// Generated code should register open generic:
-services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
-```
-
-**Implementation Notes**:
-
-- ✅ Detects when service implements open generic interface
-- ✅ Generates `typeof(IInterface<>)` and `typeof(Implementation<>)` syntax
-- ✅ Validates generic constraints match between interface and implementation
-- ✅ Supports multiple generic parameters (`IHandler`)
-- ✅ Works with explicit `As` parameter and auto-detection
-- ✅ Supports constraints (where T : class, IEntity, new())
-
----
-
-### 2. Keyed Service Registration
-
-**Priority**: 🔴 **High**
-**Status**: ✅ **Implemented** (v1.1)
-**Inspiration**: .NET 8+ keyed services, Scrutor's named registrations
-
-**Description**: Support keyed service registration for multiple implementations of the same interface.
-
-**User Story**:
-> "As a developer, I want to register multiple implementations of `IPaymentProcessor` (Stripe, PayPal, Square) and resolve them by key."
-
-**Example**:
-
-```csharp
-[Registration(As = typeof(IPaymentProcessor), Key = "Stripe")]
-public class StripePaymentProcessor : IPaymentProcessor
-{
- public Task ProcessPaymentAsync(decimal amount) { /* ... */ }
-}
-
-[Registration(As = typeof(IPaymentProcessor), Key = "PayPal")]
-public class PayPalPaymentProcessor : IPaymentProcessor
-{
- public Task ProcessPaymentAsync(decimal amount) { /* ... */ }
-}
-
-// Generated code:
-services.AddKeyedScoped("Stripe");
-services.AddKeyedScoped("PayPal");
-
-// Usage:
-public class CheckoutService
-{
- public CheckoutService([FromKeyedServices("Stripe")] IPaymentProcessor processor)
- {
- // ...
- }
-}
-```
-
-**Implementation Notes**:
-
-- ✅ Added `Key` parameter to `[Registration]` attribute
-- ✅ Generates `AddKeyed{Lifetime}()` calls
-- ✅ Supports both string and type keys
-- ✅ Works with generic types (AddKeyedScoped(typeof(IRepository<>), "Key", typeof(Repository<>)))
-
----
-
-### 3. Factory Method Registration
-
-**Priority**: 🟡 **Medium-High**
-**Status**: ✅ **Implemented** (v1.1)
-**Inspiration**: Microsoft.Extensions.DependencyInjection factories, Jab's custom instantiation
-
-**Description**: Support registering services via factory methods for complex initialization logic.
-
-**User Story**:
-> "As a developer, I want to register services that require custom initialization logic (like reading configuration, conditional setup, etc.) without creating intermediate builder classes."
-
-**Example**:
-
-```csharp
-[Registration(Lifetime.Scoped, As = typeof(IEmailSender), Factory = nameof(CreateEmailSender))]
-public class EmailSender : IEmailSender
-{
- private readonly string apiKey;
-
- private EmailSender(string apiKey) => this.apiKey = apiKey;
-
- // Factory method signature: static T Create(IServiceProvider provider)
- public static IEmailSender CreateEmailSender(IServiceProvider provider)
- {
- var config = provider.GetRequiredService();
- var apiKey = config["EmailSettings:ApiKey"] ?? throw new InvalidOperationException();
- return new EmailSender(apiKey);
- }
-
- public Task SendAsync(string to, string subject, string body) { /* ... */ }
-}
-
-// Generated code:
-services.AddScoped(sp => EmailSender.CreateEmailSender(sp));
-```
-
-**Implementation Notes**:
-
-- ✅ Added `Factory` property to `[Registration]` attribute
-- ✅ Factory method must be `static` and return the service type (interface or class)
-- ✅ Factory method must accept `IServiceProvider` as single parameter
-- ✅ Validates factory method signature at compile time
-- ✅ Generates factory delegate registration: `services.Add{Lifetime}(sp => Class.Factory(sp))`
-- ✅ Works with all lifetimes (Singleton, Scoped, Transient)
-- ✅ Supports registering as interface, as self, or multiple interfaces
-- ✅ Diagnostics: ATCDIR005 (factory method not found), ATCDIR006 (invalid signature)
-
----
-
-### 4. TryAdd* Registration
-
-**Priority**: 🟡 **Medium**
-**Status**: ✅ **Implemented** (v1.2)
-**Inspiration**: Scrutor's TryAdd support, AutoRegisterInject's "Try" variants
-
-**Description**: Support conditional registration that only adds services if not already registered.
-
-**User Story**:
-> "As a library author, I want to register default implementations that can be overridden by application code."
-
-**Example**:
-
-```csharp
-[Registration(As = typeof(ILogger), TryAdd = true)]
-public class DefaultLogger : ILogger
-{
- public void Log(string message) => Console.WriteLine(message);
-}
-
-// Generated code:
-services.TryAddScoped();
-
-// User can override:
-services.AddScoped(); // This wins
-```
-
-**Implementation Notes**:
-
-- ✅ Added `TryAdd` boolean parameter to `[Registration]` attribute
-- ✅ Generates `TryAdd{Lifetime}()` calls instead of `Add{Lifetime}()`
-- ✅ Works with factory methods: `services.TryAddScoped(sp => Factory(sp))`
-- ✅ Supports all lifetimes: TryAddSingleton, TryAddScoped, TryAddTransient
-- ✅ Works with generic types: `services.TryAddScoped(typeof(IRepository<>), typeof(Repository<>))`
-- ✅ Compatible with AsSelf and multiple interface registrations
-- ⚠️ Note: Keyed services take precedence (no TryAdd support for keyed registrations)
-- ✅ Requires `using Microsoft.Extensions.DependencyInjection.Extensions;` (automatically added to generated code)
-
----
-
-### 5. Assembly Scanning Filters
-
-**Priority**: 🟡 **Medium**
-**Status**: ✅ **Implemented** (v1.2)
-**Inspiration**: Scrutor's filtering capabilities
-
-**Description**: Provide filtering options to exclude specific types, namespaces, or patterns from transitive registration.
-
-**User Story**:
-> "As a developer, I want to exclude internal services or test utilities from automatic registration when using `includeReferencedAssemblies: true`."
-
-**Example**:
-
-```csharp
-// Option A: Exclude specific namespace (supports arrays)
-[assembly: RegistrationFilter(ExcludeNamespaces = new[] { "MyApp.Internal", "MyApp.Tests" })]
-
-// Option B: Exclude by naming pattern (supports wildcards)
-[assembly: RegistrationFilter(ExcludePatterns = new[] { "*Test*", "*Mock*" })]
-
-// Option C: Exclude types implementing specific interface
-[assembly: RegistrationFilter(ExcludeImplementing = new[] { typeof(ITestUtility) })]
-
-// Option D: Multiple filters in one attribute
-[assembly: RegistrationFilter(
- ExcludeNamespaces = new[] { "MyApp.Internal" },
- ExcludePatterns = new[] { "*Test*", "*Mock*" })]
-
-// Generated code only includes non-excluded types
-```
-
-**Implementation Notes**:
-
-- ✅ Assembly-level `RegistrationFilterAttribute` with `AllowMultiple = true`
-- ✅ Support namespace exclusion (exact match + sub-namespaces)
-- ✅ Support wildcard patterns: `*` (any characters), `?` (single character)
-- ✅ Support interface exclusion with proper generic type comparison
-- ✅ Multiple filter attributes can be applied
-- ✅ Filters applied to both current assembly and referenced assemblies
-- ✅ All properties accept arrays for multiple values
-- ✅ Pattern matching is case-insensitive
-- ✅ Sub-namespace matching: "MyApp.Internal" excludes "MyApp.Internal.Deep"
-
----
-
-### 6. Decorator Pattern Support
-
-**Priority**: 🟢 **Low-Medium** ⭐ *Highly valued by Scrutor users*
-**Status**: ✅ **Implemented** (v1.3 - January 2025)
-**Inspiration**: Scrutor's `Decorate()` method
-
-**Description**: Support decorating already-registered services with additional functionality (logging, caching, validation, etc.).
-
-**User Story**:
-> "As a developer, I want to add cross-cutting concerns (logging, caching, retry logic) to services without modifying the original implementation."
-
-**Example**:
-
-```csharp
-// Original service
-[Registration(As = typeof(IOrderService))]
-public class OrderService : IOrderService
-{
- public Task PlaceOrderAsync(Order order) { /* ... */ }
-}
-
-// Decorator (wraps original)
-[Registration(As = typeof(IOrderService), Decorator = true)]
-public class LoggingOrderServiceDecorator : IOrderService
-{
- private readonly IOrderService _inner;
- private readonly ILogger _logger;
-
- public LoggingOrderServiceDecorator(IOrderService inner, ILogger logger)
- {
- _inner = inner;
- _logger = logger;
- }
-
- public async Task PlaceOrderAsync(Order order)
- {
- _logger.LogInformation("Placing order {OrderId}", order.Id);
- await _inner.PlaceOrderAsync(order);
- _logger.LogInformation("Order {OrderId} placed successfully", order.Id);
- }
-}
-
-// Generated code:
-services.AddScoped();
-services.Decorate(); // Wraps existing registration
-```
-
-**Implementation Notes**:
-
-- ✅ Added `Decorator` boolean parameter to `[Registration]` attribute
-- ✅ Decorators must specify explicit `As` parameter (interface being decorated)
-- ✅ Decorator registration automatically comes after base service registration
-- ✅ Decorator constructor must accept the interface as first parameter
-- ✅ Supports multiple decorators (chaining) - applied in discovery order
-- ✅ Generates `Decorate()` extension methods (both generic and non-generic for open generics)
-- ✅ Uses `ActivatorUtilities.CreateInstance()` to properly inject inner service
-- ✅ Preserves service lifetime from original registration
-- ✅ Works with Singleton, Scoped, and Transient lifetimes
-- ✅ Complete test coverage with 7 unit tests
-- ✅ Documented in comprehensive decorator pattern section of docs
-
----
-
-### 7. Implementation Instance Registration
-
-**Priority**: 🟢 **Low**
-**Status**: ✅ **Implemented** (v1.4 - January 2025)
-
-**Description**: Register pre-created singleton instances via static fields, properties, or methods.
-
-**User Story**:
-> "As a developer, I want to register pre-configured singleton instances (like immutable configuration objects) without requiring factory methods or runtime initialization."
-
-**Example**:
-
-```csharp
-[Registration(As = typeof(IConfiguration), Instance = nameof(DefaultInstance))]
-public class AppConfiguration : IConfiguration
-{
- // Static field providing pre-created instance
- public static readonly AppConfiguration DefaultInstance = new()
- {
- Setting1 = "default",
- Setting2 = 42
- };
-
- private AppConfiguration() { } // Private constructor enforces singleton
-
- public string Setting1 { get; init; } = string.Empty;
- public int Setting2 { get; init; }
-}
-
-// Generated code:
-services.AddSingleton(AppConfiguration.DefaultInstance);
-```
-
-**Alternative patterns supported**:
-
-```csharp
-// Static property
-[Registration(As = typeof(ICache), Instance = nameof(Instance))]
-public class MemoryCache : ICache
-{
- public static MemoryCache Instance { get; } = new();
-}
-
-// Static method
-[Registration(As = typeof(ILogger), Instance = nameof(GetDefault))]
-public class DefaultLogger : ILogger
-{
- public static DefaultLogger GetDefault() => new();
-}
-```
-
-**Implementation Notes**:
-
-- ✅ Added `Instance` property to `[Registration]` attribute
-- ✅ Supports static fields, properties, and parameterless methods
-- ✅ Generates `services.AddSingleton(ClassName.MemberName)` or `services.AddSingleton(ClassName.Method())`
-- ✅ **Constraint**: Instance registration requires Singleton lifetime (enforced at compile-time)
-- ✅ **Constraint**: Instance and Factory parameters are mutually exclusive
-- ✅ Validates member exists and is static at compile-time
-- ✅ Diagnostics: ATCDIR007 (member not found), ATCDIR008 (not static), ATCDIR009 (mutually exclusive), ATCDIR010 (requires Singleton)
-- ✅ Works with TryAdd: `services.TryAddSingleton(ClassName.Instance)`
-- ✅ Complete test coverage with 8 unit tests
-- ✅ Demonstrated in both DependencyRegistration and PetStore samples
-
----
-
-## 💡 Nice to Have (Medium Priority)
-
-These features would improve usability but are not critical for initial adoption.
-
-### 8. Conditional Registration
-
-**Priority**: 🟢 **Low-Medium**
-**Status**: ✅ **Implemented** (v1.5 - January 2025)
-
-**Description**: Register services based on configuration values at runtime (feature flags, environment-specific services).
-
-**User Story**:
-> "As a developer, I want to register different service implementations based on configuration values (feature flags) without code changes or redeployment."
-
-**Example**:
-
-```csharp
-// appsettings.json
-{
- "Features": {
- "UseRedisCache": true
- }
-}
-
-[Registration(As = typeof(ICache), Condition = "Features:UseRedisCache")]
-public class RedisCache : ICache { }
-
-[Registration(As = typeof(ICache), Condition = "!Features:UseRedisCache")]
-public class MemoryCache : ICache { }
-
-// Generated code checks configuration at runtime
-public static IServiceCollection AddDependencyRegistrationsFromDomain(
- this IServiceCollection services,
- IConfiguration configuration) // ← IConfiguration parameter added automatically
-{
- if (configuration.GetValue("Features:UseRedisCache"))
- {
- services.AddSingleton();
- }
-
- if (!configuration.GetValue("Features:UseRedisCache"))
- {
- services.AddSingleton();
- }
-
- return services;
-}
-
-// Usage
-services.AddDependencyRegistrationsFromDomain(configuration);
-```
-
-**Implementation Notes**:
-
-- ✅ Added `Condition` property to `[Registration]` attribute
-- ✅ Supports negation with `!` prefix
-- ✅ IConfiguration parameter automatically added to all method overloads when conditional services exist
-- ✅ Generates `if (configuration.GetValue("key"))` checks wrapping registration calls
-- ✅ Configuration is NOT passed transitively to referenced assemblies (each assembly manages its own)
-- ✅ Works with all lifetimes (Singleton, Scoped, Transient)
-- ✅ Fully Native AOT compatible (simple boolean reads from configuration)
-- ✅ Thread-safe configuration reading
-- ✅ Complete test coverage with 6 unit tests
-- ✅ Demonstrated in both DependencyRegistration and PetStore samples
-- ✅ Comprehensive documentation in Conditional Registration section
-
-**Benefits**:
-
-- 🎯 Feature Flags - Enable/disable features without redeployment
-- 🌍 Environment-Specific - Different implementations for dev/staging/prod
-- 🧪 A/B Testing - Easy experimentation with different implementations
-- 💰 Cost Optimization - Disable expensive services when not needed
-- 🚀 Gradual Rollout - Safely test new implementations before full deployment
-
----
-
-### 9. Auto-Discovery by Convention
-
-**Priority**: 🟢 **Low-Medium**
-**Status**: ❌ Not Implemented
-**Inspiration**: Scrutor's convention-based scanning
-
-**Description**: Automatically register types based on naming conventions without requiring attributes.
-
-**Example**:
-
-```csharp
-// Convention: Classes ending with "Service" implement I{ClassName}
-public class UserService : IUserService { } // Auto-registered
-public class OrderService : IOrderService { } // Auto-registered
-
-// Generated code discovers these by convention
-```
-
-**Considerations**:
-
-- Conflicts with our explicit opt-in philosophy
-- May lead to unexpected registrations
-- Consider as opt-in feature with assembly-level attribute
-
----
-
-### 10. Registration Validation Diagnostics
-
-**Priority**: 🟡 **Medium**
-**Status**: ❌ Not Implemented
-
-**Description**: Provide compile-time diagnostics for common DI mistakes.
-
-**Examples**:
-
-- Warning if service has no public constructor
-- Warning if constructor parameters cannot be resolved (missing registrations)
-- Warning if circular dependencies detected
-- Error if hosted service is not registered as Singleton
-
-**Implementation**:
-
-- Analyze constructor parameters
-- Build dependency graph
-- Detect cycles and missing dependencies
-
----
-
-### 11. Multi-Interface Registration (Enhanced)
-
-**Priority**: 🟢 **Low**
-**Status**: ⚠️ Partially Implemented (auto-detects all interfaces)
-
-**Description**: Allow explicit control over which interfaces to register when a class implements multiple interfaces.
-
-**Current behavior**: Registers ALL implemented interfaces (excluding System.*)
-
-**Enhancement**: Allow selective registration of specific interfaces
-
-**Example**:
-
-```csharp
-// Register only specific interfaces
-[Registration(As = new[] { typeof(IUserService), typeof(IEmailService) })]
-public class UserService : IUserService, IEmailService, IAuditLogger
-{
- // Only IUserService and IEmailService are registered, not IAuditLogger
-}
-```
-
----
-
-## ⛔ Do Not Need (Low Priority / Out of Scope)
-
-These features either conflict with design principles or are too complex.
-
-### 12. Runtime Assembly Scanning
-
-**Reason**: Conflicts with compile-time source generation philosophy. Scrutor already handles this well for runtime scenarios.
-
-**Status**: ❌ Out of Scope
-
----
-
-### 13. Property/Field Injection
-
-**Reason**: Constructor injection is the recommended pattern. Property injection is an anti-pattern that hides dependencies.
-
-**Status**: ❌ Not Planned
-
----
-
-### 14. Auto-Wiring Based on Reflection
-
-**Reason**: Breaks AOT compatibility. Defeats the purpose of compile-time generation.
-
-**Status**: ❌ Out of Scope
-
----
-
-### 15. Service Replacement/Override at Runtime
-
-**Reason**: DI container should be immutable after configuration. Runtime replacement is fragile.
-
-**Status**: ❌ Not Planned
-
----
-
-## 📅 Proposed Implementation Order
-
-Based on priority, user demand, and implementation complexity:
-
-### Phase 1: Essential Features (v1.1 - Q1 2025) ✅ COMPLETED
-
-**Goal**: Support advanced DI patterns (generics, keyed services, factory methods)
-
-1. ✅ **Generic Interface Registration** 🔴 Critical - `IRepository`, `IHandler`
-2. ✅ **Keyed Service Registration** 🔴 High - Multiple implementations with keys (.NET 8+)
-3. ✅ **Factory Method Registration** 🟡 Medium-High - Custom initialization logic
-
-**Status**: ✅ COMPLETED (January 2025)
-**Impact**: Unlock repository pattern, multi-tenant scenarios, plugin architectures, complex initialization
-
----
-
-### Phase 2: Flexibility & Control (v1.2 - Q1 2025) ✅ COMPLETED
-
-**Goal**: Conditional registration and filtering
-
-1. ✅ **TryAdd* Registration** 🟡 Medium - Conditional registration for library scenarios
-2. ✅ **Assembly Scanning Filters** 🟡 Medium - Exclude namespaces/patterns from transitive registration
-
-**Status**: ✅ COMPLETED (January 2025)
-**Impact**: Better control over transitive registration, library author support
-
----
-
-### Phase 2.5: Advanced Patterns (v1.3 - Q1 2025) ✅ COMPLETED
-
-**Goal**: Decorator pattern for cross-cutting concerns
-
-1. ✅ **Decorator Pattern Support** 🟢 Low-Medium ⭐ - Wrap services with logging, caching, validation
-
-**Status**: ✅ COMPLETED (January 2025)
-**Impact**: Enterprise-grade cross-cutting concerns without code modification
-
----
-
-### Phase 3: Advanced Scenarios (v1.4 - Q1 2025) ✅ COMPLETED
-
-**Goal**: Instance registration for pre-created singletons
-
-1. ✅ **Implementation Instance Registration** 🟢 Low - Pre-created singleton instances
-
-**Status**: ✅ COMPLETED (January 2025)
-**Impact**: Support immutable configuration objects and pre-initialized singletons
-
----
-
-### Phase 4: Advanced Scenarios (v1.5 - Q2 2025)
-
-**Goal**: Validation and diagnostics
-
-1. **Multi-Interface Registration** 🟢 Low - Selective interface registration
-2. **Registration Validation Diagnostics** 🟡 Medium - Compile-time warnings for missing dependencies
-3. **Conditional Registration** 🟢 Low-Medium - Feature flag-based registration
-
-**Estimated effort**: 3-4 weeks
-**Impact**: Catch DI mistakes at compile time, support feature toggles
-
----
-
-### Phase 5: Enterprise Features (v2.0 - Q3 2025)
-
-**Goal**: Convention-based patterns
-
-1. **Auto-Discovery by Convention** 🟢 Low-Medium - Optional convention-based registration
-
-**Estimated effort**: 2-3 weeks
-**Impact**: Reduce boilerplate further with conventions
-
----
-
-### Feature Prioritization Matrix
-
-| Feature | Priority | User Demand | Complexity | Phase | Status |
-|---------|----------|-------------|------------|-------|--------|
-| Generic Interface Registration | 🔴 Critical | ⭐⭐⭐ | High | 1.1 | ✅ Done |
-| Keyed Service Registration | 🔴 High | ⭐⭐⭐ | Medium | 1.1 | ✅ Done |
-| Factory Method Registration | 🟡 Med-High | ⭐⭐ | Medium | 1.1 | ✅ Done |
-| TryAdd* Registration | 🟡 Medium | ⭐⭐ | Low | 1.2 | ✅ Done |
-| Assembly Scanning Filters | 🟡 Medium | ⭐⭐ | Medium | 1.2 | ✅ Done |
-| Decorator Pattern | 🟢 Low-Med | ⭐⭐⭐ | Very High | 1.3 | ✅ Done |
-| Implementation Instance Registration | 🟢 Low | ⭐ | Medium | 1.4 | ✅ Done |
-| Multi-Interface Registration | 🟢 Low | ⭐ | Low | 1.5 | 📋 Planned |
-| Registration Validation | 🟡 Medium | ⭐⭐ | High | 1.5 | 📋 Planned |
-| Conditional Registration | 🟢 Low-Med | ⭐ | Medium | 1.5 | 📋 Planned |
-| Convention-Based Discovery | 🟢 Low-Med | ⭐⭐ | Medium | 2.0 | 📋 Planned |
-
----
-
-## 🎯 Success Metrics
-
-To determine if these features are meeting user needs:
-
-1. **Adoption Rate** - NuGet download statistics
-2. **GitHub Issues** - Track feature requests and pain points
-3. **Performance Benchmarks** - Compare startup time vs. Scrutor/runtime registration
-4. **Community Feedback** - Surveys, blog posts, conference talks
-5. **Real-World Usage** - Case studies from production applications
-
----
-
-## 📝 Notes
-
-### Design Philosophy
-
-- **Guiding Principle**: **Explicit opt-in**, **compile-time safety**, **AOT-compatible**
-- **Trade-offs**: We prefer attribute-based registration over convention-based to maintain predictability
-- **Scrutor vs. Our Approach**: Scrutor is runtime-based (assembly scanning), we are compile-time (source generation). Both have their place.
-- **Performance Focus**: Like Jab, we eliminate reflection overhead by generating code at compile time
-
-### Key Differences from Scrutor
-
-**What we do differently**:
-
-1. **Compile-time generation** - Zero startup overhead vs. Scrutor's runtime scanning
-2. **Per-type attributes** - Explicit `[Registration]` on each service vs. assembly-wide conventions
-3. **Transitive registration** - Our 4-overload approach vs. Scrutor's fluent API
-4. **AOT-friendly** - Native AOT compatible out of the box
-
-**What we learn from Scrutor**:
-
-- ⭐ **Generic interface support** is critical for repository/handler patterns
-- ⭐ **Decorator pattern** is highly valued (cross-cutting concerns)
-- ⭐ **Filtering capabilities** prevent unintended registrations in large codebases
-- ⚠️ Runtime flexibility (Scrutor's strength) is less important for our compile-time approach
-
-### Lessons from AutoRegisterInject
-
-**From 119 stars and attribute-based approach**:
-
-- **Decentralized registration** reduces merge conflicts in teams
-- **Assembly-specific extension methods** enable modular registration
-- **TryAdd variants** are important for library authors
-- **Keyed services** support multi-tenant scenarios (.NET 8+)
-
-### Lessons from Jab
-
-**From performance-focused DI container**:
-
-- **Compile-time validation** catches errors before runtime
-- **Readable generated code** builds developer trust
-- **Zero reflection** is essential for AOT and startup performance
-- **Clean stack traces** improve debugging experience
-
----
-
-## 🔗 Related Resources
-
-- **Scrutor**: (4.2k⭐, runtime scanning)
-- **AutoRegisterInject**: (119⭐, attribute-based)
-- **Jab**: (compile-time DI container)
-- **Microsoft.Extensions.DependencyInjection**:
-- **Our Documentation**: See `/docs/generators/DependencyRegistration.md`
-- **Sample Projects**: See `/sample/PetStore.Api` for complete example
-
----
-
-**Last Updated**: 2025-01-17 (Implementation Instance Registration completed)
-**Version**: 1.4
-**Research Date**: January 2025 (Scrutor v6.1.0)
-**Maintained By**: Atc.SourceGenerators Team
diff --git a/docs/DependencyRegistrationGenerators-Samples.md b/docs/DependencyRegistrationGenerators-Samples.md
deleted file mode 100644
index 7aa40b7..0000000
--- a/docs/DependencyRegistrationGenerators-Samples.md
+++ /dev/null
@@ -1,235 +0,0 @@
-# Dependency Registration Sample
-
-## 🎯 Focus
-
-This sample demonstrates the **DependencyRegistrationGenerator** in a multi-project setup with layered architecture. The focus is on:
-
-- **Zero boilerplate DI registration** across multiple projects
-- **Auto-detection** of implemented interfaces
-- **Multi-interface support** for services implementing multiple contracts
-- **Assembly-specific extension methods** for clean project separation
-- **Lifetime management** (Singleton, Scoped, Transient)
-
-## 📁 Sample Projects
-
-- **Atc.SourceGenerators.DependencyRegistration** - Console application (entry point)
-- **Atc.SourceGenerators.DependencyRegistration.Domain** - Domain layer with services
-
-## 🏗️ Architecture
-
-```mermaid
-graph TB
- subgraph "Atc.SourceGenerators.DependencyRegistration (Console App)"
- Program[Program.cs]
- SC[ServiceCollection]
- end
-
- subgraph "Atc.SourceGenerators.DependencyRegistration.Domain"
- US[UserService]
- CS[CacheService]
- ES[EmailService]
- IUS[IUserService]
- ICS[ICacheService]
- IES[IEmailService]
- INS[INotificationService]
-
- US -->|implements| IUS
- CS -->|implements| ICS
- ES -->|implements| IES
- ES -->|implements| INS
- end
-
- subgraph "Generated Code"
- EXT1["AddDependencyRegistrationsFromAtcSourceGeneratorsDependencyRegistration()"]
- EXT2["AddDependencyRegistrationsFromAtcSourceGeneratorsDependencyRegistrationDomain()"]
- end
-
- Program --> SC
- SC --> EXT1
- SC --> EXT2
- EXT1 -->|registers| Program
- EXT2 -->|registers| US
- EXT2 -->|registers| CS
- EXT2 -->|registers| ES
-
- style US fill:#0969da
- style CS fill:#0969da
- style ES fill:#0969da
- style EXT1 fill:#2ea44f
- style EXT2 fill:#2ea44f
-```
-
-## 🔄 Registration Flow
-
-```mermaid
-sequenceDiagram
- participant App as Program.cs
- participant Gen as Source Generator
- participant DI as ServiceCollection
-
- Note over Gen: Build Time
- Gen->>Gen: Scan for [Registration] attributes
- Gen->>Gen: Detect implemented interfaces
- Gen->>Gen: Generate AddDependencyRegistrationsFromXXX()
-
- Note over App,DI: Runtime
- App->>DI: AddDependencyRegistrationsFromDomain()
- DI->>DI: services.AddScoped()
- DI->>DI: services.AddSingleton()
- DI->>DI: services.AddScoped()
- DI->>DI: services.AddScoped()
- DI-->>App: Configured ServiceProvider
-```
-
-## 💻 Code Example
-
-### Domain Layer Services
-
-```csharp
-using Atc.DependencyInjection;
-
-namespace Atc.SourceGenerators.DependencyRegistration.Domain;
-
-// Auto-detected as IUserService
-[Registration(Lifetime.Scoped)]
-public class UserService : IUserService
-{
- public void CreateUser(string name)
- {
- Console.WriteLine($"Creating user: {name}");
- }
-}
-
-// Auto-detected as ICacheService
-[Registration] // Defaults to Singleton
-public class CacheService : ICacheService
-{
- public void Set(string key, object value)
- {
- Console.WriteLine($"Caching {key}");
- }
-}
-
-// Multi-interface example - registers against BOTH interfaces
-[Registration(Lifetime.Scoped)]
-public class EmailService : IEmailService, INotificationService
-{
- public void SendEmail(string to, string subject)
- {
- Console.WriteLine($"Email to {to}: {subject}");
- }
-
- public void Notify(string message)
- {
- Console.WriteLine($"Notification: {message}");
- }
-}
-```
-
-### Application Setup
-
-**Option 1 - Manual Registration:**
-
-```csharp
-using Atc.DependencyInjection;
-using Microsoft.Extensions.DependencyInjection;
-
-var services = new ServiceCollection();
-
-// One line per project - that's it!
-services.AddDependencyRegistrationsFromAtcSourceGeneratorsDependencyRegistration();
-services.AddDependencyRegistrationsFromAtcSourceGeneratorsDependencyRegistrationDomain();
-
-var provider = services.BuildServiceProvider();
-
-// Resolve and use services
-var userService = provider.GetRequiredService();
-userService.CreateUser("John Doe");
-
-var emailService = provider.GetRequiredService();
-emailService.SendEmail("john@example.com", "Welcome");
-
-// Same instance via second interface!
-var notifier = provider.GetRequiredService();
-notifier.Notify("System is ready");
-```
-
-**Option 2 - Transitive Registration (Recommended):**
-
-```csharp
-using Atc.DependencyInjection;
-using Microsoft.Extensions.DependencyInjection;
-
-var services = new ServiceCollection();
-
-// Single call automatically registers both projects!
-services.AddDependencyRegistrationsFromAtcSourceGeneratorsDependencyRegistration(includeReferencedAssemblies: true);
-
-var provider = services.BuildServiceProvider();
-
-// All services available, including from Domain layer
-var userService = provider.GetRequiredService();
-userService.CreateUser("John Doe");
-
-var emailService = provider.GetRequiredService();
-emailService.SendEmail("john@example.com", "Welcome");
-
-// Same instance via second interface!
-var notifier = provider.GetRequiredService();
-notifier.Notify("System is ready");
-```
-
-**All Available Overloads:**
-
-```csharp
-// Overload 1: Default (no transitive registration)
-services.AddDependencyRegistrationsFromYourProject();
-
-// Overload 2: Auto-detect ALL referenced assemblies recursively
-services.AddDependencyRegistrationsFromYourProject(includeReferencedAssemblies: true);
-
-// Overload 3: Register specific referenced assembly (short or full name)
-services.AddDependencyRegistrationsFromYourProject("Domain");
-services.AddDependencyRegistrationsFromYourProject("MyApp.Domain");
-
-// Overload 4: Register multiple specific assemblies
-services.AddDependencyRegistrationsFromYourProject("Domain", "DataAccess", "Infrastructure");
-```
-
-## 📝 Generated Code
-
-The generator creates this extension method in each project:
-
-```csharp
-//
-namespace Atc.DependencyInjection;
-
-public static class ServiceCollectionExtensions
-{
- public static IServiceCollection AddDependencyRegistrationsFromAtcSourceGeneratorsDependencyRegistrationDomain(
- this IServiceCollection services)
- {
- services.AddScoped();
- services.AddSingleton();
- services.AddScoped();
- services.AddScoped();
-
- return services;
- }
-}
-```
-
-## ✨ Key Takeaways
-
-1. **Zero Configuration**: Services are automatically registered against all implemented interfaces
-2. **Type Safety**: Compile-time errors if interfaces don't match or lifetimes conflict
-3. **Multi-Project**: Each project gets its own `AddDependencyRegistrationsFromXXX()` method
-4. **Multi-Interface**: One service can be registered against multiple interfaces automatically
-5. **Smart Filtering**: System interfaces (IDisposable, etc.) are automatically excluded
-
-## 🔗 Related Documentation
-
-- [DependencyRegistration Generator Guide](DependencyRegistrationGenerators.md) - Full generator documentation
-- [Mapping Sample](ObjectMappingGenerators-Samples.md) - Object mapping example
-- [OptionsBinding Sample](OptionsBinding-Samples.md) - Configuration binding example
-- [PetStore API Sample](PetStoreApi-Samples.md) - Complete application using all generators
diff --git a/docs/DependencyRegistrationGenerators.md b/docs/DependencyRegistrationGenerators.md
deleted file mode 100644
index a83bca9..0000000
--- a/docs/DependencyRegistrationGenerators.md
+++ /dev/null
@@ -1,3184 +0,0 @@
-# 🎯 Dependency Registration Generator
-
-Automatically register services in the dependency injection container using attributes instead of manual registration code. The generator creates type-safe registration code at compile time, eliminating boilerplate and reducing errors.
-
-**Key Benefits:**
-
-- 🎯 **Zero boilerplate** - Attribute-based registration eliminates manual `AddScoped()` calls
-- 🚀 **Compile-time safety** - Catch registration errors at build time, not runtime
-- ⚡ **Auto-detection** - Automatically registers all implemented interfaces
-- 🔧 **Multi-project support** - Smart naming for assembly-specific registration methods
-- 🎨 **Advanced patterns** - Generics, keyed services, factories, decorators, and more
-
-**Quick Example:**
-
-```csharp
-// Input: Attribute decoration
-[Registration(Lifetime.Scoped)]
-public class UserService : IUserService { }
-
-// Generated output
-services.AddScoped();
-```
-
-## 📖 Documentation Navigation
-
-- **[📋 Feature Roadmap](DependencyRegistrationGenerators-FeatureRoadmap.md)** - See all implemented and planned features
-- **[🎯 Sample Projects](DependencyRegistrationGenerators-Samples.md)** - Working code examples with architecture diagrams
-
-## 📑 Table of Contents
-
-- [🎯 Dependency Registration Generator](#-dependency-registration-generator)
- - [� Documentation Navigation](#-documentation-navigation)
- - [📑 Table of Contents](#-table-of-contents)
- - [🚀 Get Started - Quick Guide](#-get-started---quick-guide)
- - [📂 Project Structure](#-project-structure)
- - [1️⃣ Setup Projects](#1️⃣-setup-projects)
- - [2️⃣ Data Access Layer (PetStore.DataAccess) 💾](#2️⃣-data-access-layer-petstoredataaccess-)
- - [3️⃣ Domain Layer (PetStore.Domain) 🧠](#3️⃣-domain-layer-petstoredomain-)
- - [4️⃣ API Layer (PetStore.Api) 🌐](#4️⃣-api-layer-petstoreapi-)
- - [5️⃣ Program.cs (Minimal API Setup) ⚡](#5️⃣-programcs-minimal-api-setup-)
- - [🎨 What Gets Generated](#-what-gets-generated)
- - [6️⃣ Testing the Application 🧪](#6️⃣-testing-the-application-)
- - [🔍 Viewing Generated Code (Optional)](#-viewing-generated-code-optional)
- - [🎯 Key Takeaways](#-key-takeaways)
- - [📦 Installation](#-installation)
- - [💡 Basic Usage](#-basic-usage)
- - [1️⃣ Add Using Directives](#1️⃣-add-using-directives)
- - [2️⃣ Decorate Your Services](#2️⃣-decorate-your-services)
- - [3️⃣ Register in DI Container](#3️⃣-register-in-di-container)
- - [✨ Features](#-features)
- - [🏗️ Multi-Project Setup](#️-multi-project-setup)
- - [📁 Example Structure](#-example-structure)
- - [⚡ Program.cs Registration](#-programcs-registration)
- - [🔄 Transitive Dependency Registration](#-transitive-dependency-registration)
- - [🏷️ Method Naming Convention](#️-method-naming-convention)
- - [✨ Smart Naming](#-smart-naming)
- - [🔍 Auto-Detection](#-auto-detection)
- - [1️⃣ Single Interface](#1️⃣-single-interface)
- - [🔢 Multiple Interfaces](#-multiple-interfaces)
- - [🧹 System Interfaces Filtered](#-system-interfaces-filtered)
- - [🎯 Explicit Override](#-explicit-override)
- - [🔀 Register As Both Interface and Concrete Type](#-register-as-both-interface-and-concrete-type)
- - [⏱️ Service Lifetimes](#️-service-lifetimes)
- - [🔒 Singleton (Default)](#-singleton-default)
- - [🔄 Scoped](#-scoped)
- - [⚡ Transient](#-transient)
- - [🚀 Native AOT Compatibility](#-native-aot-compatibility)
- - [✅ Why It Works](#-why-it-works)
- - [🎯 Key Benefits](#-key-benefits)
- - [🚀 Native AOT Example](#-native-aot-example)
- - [⚙️ RegistrationAttribute Parameters](#️-registrationattribute-parameters)
- - [📝 Examples](#-examples)
- - [🛡️ Diagnostics](#️-diagnostics)
- - [❌ ATCDIR001: As Type Must Be Interface or Abstract Class](#-atcdir001-as-type-must-be-interface-or-abstract-class)
- - [❌ ATCDIR002: Class Does Not Implement Interface or Inherit Abstract Class](#-atcdir002-class-does-not-implement-interface-or-inherit-abstract-class)
- - [⚠️ ATCDIR003: Duplicate Registration with Different Lifetime](#️-atcdir003-duplicate-registration-with-different-lifetime)
- - [❌ ATCDIR004: Hosted Services Must Use Singleton Lifetime](#-atcdir004-hosted-services-must-use-singleton-lifetime)
- - [🔷 Generic Interface Registration](#-generic-interface-registration)
- - [Single Type Parameter](#single-type-parameter)
- - [Multiple Type Parameters](#multiple-type-parameters)
- - [Complex Constraints](#complex-constraints)
- - [Explicit Generic Registration](#explicit-generic-registration)
- - [🔑 Keyed Service Registration](#-keyed-service-registration)
- - [String Keys](#string-keys)
- - [Generic Keyed Services](#generic-keyed-services)
- - [🏭 Factory Method Registration](#-factory-method-registration)
- - [Basic Factory Method](#basic-factory-method)
- - [Factory Method Requirements](#factory-method-requirements)
- - [Factory Method with Multiple Interfaces](#factory-method-with-multiple-interfaces)
- - [Factory Method Best Practices](#factory-method-best-practices)
- - [Factory Method Diagnostics](#factory-method-diagnostics)
- - [📦 Instance Registration](#-instance-registration)
- - [Basic Instance Registration (Static Field)](#basic-instance-registration-static-field)
- - [Instance Registration with Static Property](#instance-registration-with-static-property)
- - [Instance Registration with Static Method](#instance-registration-with-static-method)
- - [Instance Registration Requirements](#instance-registration-requirements)
- - [Instance Registration with Multiple Interfaces](#instance-registration-with-multiple-interfaces)
- - [Instance Registration Best Practices](#instance-registration-best-practices)
- - [Instance Registration Diagnostics](#instance-registration-diagnostics)
- - [Instance vs Factory Method](#instance-vs-factory-method)
- - [🔄 TryAdd\* Registration](#-tryadd-registration)
- - [Basic TryAdd Registration](#basic-tryadd-registration)
- - [How TryAdd Works](#how-tryadd-works)
- - [Library Author Pattern](#library-author-pattern)
- - [TryAdd with Different Lifetimes](#tryadd-with-different-lifetimes)
- - [TryAdd with Factory Methods](#tryadd-with-factory-methods)
- - [TryAdd with Generic Types](#tryadd-with-generic-types)
- - [TryAdd with Multiple Interfaces](#tryadd-with-multiple-interfaces)
- - [TryAdd Best Practices](#tryadd-best-practices)
- - [Important Notes](#important-notes)
- - [🚫 Assembly Scanning Filters](#-assembly-scanning-filters)
- - [Basic Filter Usage](#basic-filter-usage)
- - [Namespace Exclusion](#namespace-exclusion)
- - [Pattern Exclusion](#pattern-exclusion)
- - [Interface Exclusion](#interface-exclusion)
- - [Combining Multiple Filters](#combining-multiple-filters)
- - [Multiple Filter Attributes](#multiple-filter-attributes)
- - [Real-World Example](#real-world-example)
- - [Filter Priority and Behavior](#filter-priority-and-behavior)
- - [Verification](#verification)
- - [Best Practices](#best-practices)
- - [🎯 Runtime Filtering](#-runtime-filtering)
- - [Basic Usage](#basic-usage)
- - [🔹 Filter by Type](#-filter-by-type)
- - [🔹 Filter by Namespace](#-filter-by-namespace)
- - [🔹 Filter by Pattern](#-filter-by-pattern)
- - [🔹 Combining Filters](#-combining-filters)
- - [🔹 Filters with Transitive Registration](#-filters-with-transitive-registration)
- - [Runtime vs. Compile-Time Filtering](#runtime-vs-compile-time-filtering)
- - [Complete Example: Multi-Application Scenario](#complete-example-multi-application-scenario)
- - [Best Practices](#best-practices-1)
- - [Verification](#verification-1)
- - [🎨 Decorator Pattern](#-decorator-pattern)
- - [✨ How It Works](#-how-it-works)
- - [📝 Basic Example](#-basic-example)
- - [Generated Code](#generated-code)
- - [🔄 Multiple Decorators](#-multiple-decorators)
- - [🎯 Common Use Cases](#-common-use-cases)
- - [1. Logging/Auditing](#1-loggingauditing)
- - [2. Caching](#2-caching)
- - [3. Validation](#3-validation)
- - [4. Retry Logic](#4-retry-logic)
- - [⚠️ Important Notes](#️-important-notes)
- - [🔍 Complete Example](#-complete-example)
- - [🎛️ Conditional Registration](#️-conditional-registration)
- - [✨ How It Works](#-how-it-works-1)
- - [📝 Basic Example](#-basic-example-1)
- - [Generated Code](#generated-code-1)
- - [🔄 Negation Support](#-negation-support)
- - [🎯 Common Use Cases](#-common-use-cases-1)
- - [1. Feature Flags](#1-feature-flags)
- - [2. Environment-Specific Services](#2-environment-specific-services)
- - [3. A/B Testing](#3-ab-testing)
- - [4. Cost Optimization](#4-cost-optimization)
- - [🎨 Advanced Scenarios](#-advanced-scenarios)
- - [Multiple Conditional Services](#multiple-conditional-services)
- - [Combining with Different Lifetimes](#combining-with-different-lifetimes)
- - [Mixing Conditional and Unconditional](#mixing-conditional-and-unconditional)
- - [⚙️ Configuration Best Practices](#️-configuration-best-practices)
- - [🔍 IConfiguration Parameter Behavior](#-iconfiguration-parameter-behavior)
- - [⚠️ Important Notes](#️-important-notes-1)
- - [✅ Benefits](#-benefits)
- - [📝 Complete Example](#-complete-example-1)
- - [📚 Additional Examples](#-additional-examples)
-
----
-
-## 🚀 Get Started - Quick Guide
-
-This guide demonstrates a realistic 3-layer architecture for a PetStore application using minimal APIs.
-
-### 📂 Project Structure
-
-```
-PetStore.sln
-├── PetStore.Api/ (Presentation layer)
-├── PetStore.Domain/ (Business logic layer)
-└── PetStore.DataAccess/ (Data access layer)
-```
-
-### 1️⃣ Setup Projects
-
-**PetStore.DataAccess.csproj** (Base layer):
-
-```xml
-
-
- net9.0
- enable
- enable
-
-
-
-
-
-
-
-```
-
-**PetStore.Domain.csproj** (Middle layer):
-
-```xml
-
-
- net9.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-```
-
-**PetStore.Api.csproj** (Top layer):
-
-```xml
-
-
- net9.0
- enable
- enable
-
-
-
-
-
-
-
-
-```
-
-> **Note:** The `Microsoft.Extensions.DependencyInjection.Abstractions` package is needed for projects that use the `IServiceCollection` extension methods. Logging requires `Microsoft.Extensions.Logging.Abstractions`.
-
-### 2️⃣ Data Access Layer (PetStore.DataAccess) 💾
-
-**Models/Pet.cs**:
-
-```csharp
-namespace PetStore.DataAccess.Models;
-
-public class Pet
-{
- public int Id { get; set; }
- public required string Name { get; set; }
- public required string Species { get; set; }
- public int Age { get; set; }
-}
-```
-
-**Repositories/IPetRepository.cs**:
-
-```csharp
-namespace PetStore.DataAccess.Repositories;
-
-public interface IPetRepository
-{
- Task GetByIdAsync(int id);
- Task> GetAllAsync();
- Task CreateAsync(Pet pet);
- Task UpdateAsync(Pet pet);
- Task DeleteAsync(int id);
-}
-```
-
-**Repositories/PetRepository.cs**:
-
-```csharp
-using Atc.DependencyInjection;
-using PetStore.DataAccess.Models;
-
-namespace PetStore.DataAccess.Repositories;
-
-[Registration(Lifetime.Scoped)]
-public class PetRepository : IPetRepository
-{
- // In-memory storage for demo purposes
- private static readonly List InMemoryPets = new()
- {
- new Pet { Id = 1, Name = "Buddy", Species = "Dog", Age = 3 },
- new Pet { Id = 2, Name = "Whiskers", Species = "Cat", Age = 5 },
- new Pet { Id = 3, Name = "Goldie", Species = "Fish", Age = 1 }
- };
-
- private static int _nextId = 4;
-
- public Task GetByIdAsync(int id)
- {
- var pet = InMemoryPets.FirstOrDefault(p => p.Id == id);
- return Task.FromResult(pet);
- }
-
- public Task> GetAllAsync()
- {
- return Task.FromResult(InMemoryPets.AsEnumerable());
- }
-
- public Task CreateAsync(Pet pet)
- {
- pet.Id = _nextId++;
- InMemoryPets.Add(pet);
- return Task.FromResult(pet.Id);
- }
-
- public Task UpdateAsync(Pet pet)
- {
- var existing = InMemoryPets.FirstOrDefault(p => p.Id == pet.Id);
- if (existing is null) return Task.FromResult(false);
-
- existing.Name = pet.Name;
- existing.Species = pet.Species;
- existing.Age = pet.Age;
- return Task.FromResult(true);
- }
-
- public Task DeleteAsync(int id)
- {
- var pet = InMemoryPets.FirstOrDefault(p => p.Id == id);
- if (pet is null) return Task.FromResult(false);
-
- InMemoryPets.Remove(pet);
- return Task.FromResult(true);
- }
-}
-```
-
-### 3️⃣ Domain Layer (PetStore.Domain) 🧠
-
-**Models/PetDto.cs**:
-
-```csharp
-namespace PetStore.Domain.Models;
-
-public record PetDto(int Id, string Name, string Species, int Age);
-
-public record CreatePetRequest(string Name, string Species, int Age);
-
-public record UpdatePetRequest(string Name, string Species, int Age);
-
-public record ValidationResult(bool IsValid, List Errors);
-```
-
-**Services/IPetService.cs**:
-
-```csharp
-namespace PetStore.Domain.Services;
-
-public interface IPetService
-{
- Task GetPetAsync(int id);
- Task> GetAllPetsAsync();
- Task CreatePetAsync(CreatePetRequest request);
- Task UpdatePetAsync(int id, UpdatePetRequest request);
- Task DeletePetAsync(int id);
-}
-```
-
-**Services/PetService.cs**:
-
-```csharp
-using Atc.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using PetStore.DataAccess.Models;
-using PetStore.DataAccess.Repositories;
-using PetStore.Domain.Models;
-
-namespace PetStore.Domain.Services;
-
-[Registration(Lifetime.Scoped)]
-public class PetService : IPetService
-{
- private readonly IPetRepository _repository;
- private readonly ILogger _logger;
-
- public PetService(IPetRepository repository, ILogger logger)
- {
- _repository = repository;
- _logger = logger;
- }
-
- public async Task GetPetAsync(int id)
- {
- _logger.LogInformation("Getting pet with ID {PetId}", id);
- var pet = await _repository.GetByIdAsync(id);
- return pet is not null ? MapToDto(pet) : null;
- }
-
- public async Task> GetAllPetsAsync()
- {
- _logger.LogInformation("Getting all pets");
- var pets = await _repository.GetAllAsync();
- return pets.Select(MapToDto);
- }
-
- public async Task CreatePetAsync(CreatePetRequest request)
- {
- _logger.LogInformation("Creating pet: {PetName}", request.Name);
- var pet = new Pet
- {
- Name = request.Name,
- Species = request.Species,
- Age = request.Age
- };
- return await _repository.CreateAsync(pet);
- }
-
- public async Task UpdatePetAsync(int id, UpdatePetRequest request)
- {
- _logger.LogInformation("Updating pet with ID {PetId}", id);
- var pet = new Pet
- {
- Id = id,
- Name = request.Name,
- Species = request.Species,
- Age = request.Age
- };
- return await _repository.UpdateAsync(pet);
- }
-
- public async Task DeletePetAsync(int id)
- {
- _logger.LogInformation("Deleting pet with ID {PetId}", id);
- return await _repository.DeleteAsync(id);
- }
-
- private static PetDto MapToDto(Pet pet) => new(pet.Id, pet.Name, pet.Species, pet.Age);
-}
-```
-
-**Validators/IPetValidator.cs**:
-
-```csharp
-using PetStore.Domain.Models;
-
-namespace PetStore.Domain.Validators;
-
-public interface IPetValidator
-{
- ValidationResult Validate(CreatePetRequest request);
-}
-```
-
-**Validators/PetValidator.cs**:
-
-```csharp
-using Atc.DependencyInjection;
-using PetStore.Domain.Models;
-
-namespace PetStore.Domain.Validators;
-
-[Registration] // Default Singleton lifetime
-public class PetValidator : IPetValidator
-{
- public ValidationResult Validate(CreatePetRequest request)
- {
- var errors = new List();
-
- if (string.IsNullOrWhiteSpace(request.Name))
- errors.Add("Pet name is required");
-
- if (request.Age < 0)
- errors.Add("Pet age must be positive");
-
- return new ValidationResult(errors.Count == 0, errors);
- }
-}
-```
-
-### 4️⃣ API Layer (PetStore.Api) 🌐
-
-**Handlers/IPetHandlers.cs**:
-
-```csharp
-namespace PetStore.Api.Handlers;
-
-public interface IPetHandlers
-{
- void MapEndpoints(IEndpointRouteBuilder app);
-}
-```
-
-**Handlers/PetHandlers.cs**:
-
-```csharp
-using Atc.DependencyInjection;
-using PetStore.Domain.Models;
-using PetStore.Domain.Services;
-using PetStore.Domain.Validators;
-
-namespace PetStore.Api.Handlers;
-
-[Registration] // Default Singleton lifetime
-public class PetHandlers : IPetHandlers
-{
- public void MapEndpoints(IEndpointRouteBuilder app)
- {
- var pets = app.MapGroup("/api/pets").WithTags("Pets");
-
- pets.MapGet("/", GetAllPets)
- .WithName("GetAllPets");
-
- pets.MapGet("/{id:int}", GetPet)
- .WithName("GetPet");
-
- pets.MapPost("/", CreatePet)
- .WithName("CreatePet");
-
- pets.MapPut("/{id:int}", UpdatePet)
- .WithName("UpdatePet");
-
- pets.MapDelete("/{id:int}", DeletePet)
- .WithName("DeletePet");
- }
-
- private static async Task GetAllPets(IPetService petService)
- {
- var pets = await petService.GetAllPetsAsync();
- return Results.Ok(pets);
- }
-
- private static async Task GetPet(int id, IPetService petService)
- {
- var pet = await petService.GetPetAsync(id);
- return pet is not null ? Results.Ok(pet) : Results.NotFound();
- }
-
- private static async Task CreatePet(
- CreatePetRequest request,
- IPetService petService,
- IPetValidator validator)
- {
- var validation = validator.Validate(request);
- if (!validation.IsValid)
- return Results.BadRequest(new { errors = validation.Errors });
-
- var id = await petService.CreatePetAsync(request);
- return Results.Created($"/api/pets/{id}", new { id });
- }
-
- private static async Task UpdatePet(
- int id,
- UpdatePetRequest request,
- IPetService petService)
- {
- var success = await petService.UpdatePetAsync(id, request);
- return success ? Results.NoContent() : Results.NotFound();
- }
-
- private static async Task DeletePet(int id, IPetService petService)
- {
- var success = await petService.DeletePetAsync(id);
- return success ? Results.NoContent() : Results.NotFound();
- }
-}
-```
-
-### 5️⃣ Program.cs (Minimal API Setup) ⚡
-
-**Option 1 - Manual Registration (Scenario A):**
-
-```csharp
-using Atc.DependencyInjection;
-using PetStore.Api.Handlers;
-
-var builder = WebApplication.CreateBuilder(args);
-
-// Add services to the container
-builder.Services.AddEndpointsApiExplorer();
-builder.Services.AddSwaggerGen();
-
-// Register all services from all three layers manually
-builder.Services.AddDependencyRegistrationsFromDataAccess();
-builder.Services.AddDependencyRegistrationsFromDomain();
-builder.Services.AddDependencyRegistrationsFromApi();
-
-var app = builder.Build();
-
-// Configure the HTTP request pipeline
-if (app.Environment.IsDevelopment())
-{
- app.UseSwagger();
- app.UseSwaggerUI();
-}
-
-app.UseHttpsRedirection();
-
-// Map endpoints using handler
-var petHandlers = app.Services.GetRequiredService();
-petHandlers.MapEndpoints(app);
-
-app.Run();
-```
-
-**Option 2 - Transitive Registration (Scenario B - Recommended):**
-
-```csharp
-using Atc.DependencyInjection;
-using PetStore.Api.Handlers;
-
-var builder = WebApplication.CreateBuilder(args);
-
-// Add services to the container
-builder.Services.AddEndpointsApiExplorer();
-builder.Services.AddSwaggerGen();
-
-// Single call registers all services from Domain + DataAccess automatically!
-builder.Services.AddDependencyRegistrationsFromDomain(includeReferencedAssemblies: true);
-
-// Only need to register API layer services separately
-builder.Services.AddDependencyRegistrationsFromApi();
-
-var app = builder.Build();
-
-// Configure the HTTP request pipeline
-if (app.Environment.IsDevelopment())
-{
- app.UseSwagger();
- app.UseSwaggerUI();
-}
-
-app.UseHttpsRedirection();
-
-// Map endpoints using handler
-var petHandlers = app.Services.GetRequiredService();
-petHandlers.MapEndpoints(app);
-
-app.Run();
-```
-
-### 🎨 What Gets Generated
-
-For each project, the generator creates an assembly-specific extension method (with smart naming):
-
-**PetStore.DataAccess** → `AddDependencyRegistrationsFromDataAccess()` (suffix "DataAccess" is unique)
-
-```csharp
-services.AddScoped();
-```
-
-**PetStore.Domain** → `AddDependencyRegistrationsFromDomain()` (suffix "Domain" is unique)
-
-```csharp
-services.AddScoped();
-services.AddSingleton();
-```
-
-**PetStore.Api** → `AddDependencyRegistrationsFromApi()` (suffix "Api" is unique)
-
-```csharp
-services.AddSingleton();
-```
-
-### 6️⃣ Testing the Application 🧪
-
-**Build and run:**
-
-```bash
-dotnet run --project PetStore.Api
-```
-
-**Test the endpoints:**
-
-```bash
-# Get all pets
-curl http://localhost:5265/api/pets/
-
-# Get specific pet
-curl http://localhost:5265/api/pets/1
-
-# Create a new pet
-curl -X POST http://localhost:5265/api/pets/ \
- -H "Content-Type: application/json" \
- -d '{"name":"Max","species":"Dog","age":2}'
-
-# Test validation (should return errors)
-curl -X POST http://localhost:5265/api/pets/ \
- -H "Content-Type: application/json" \
- -d '{"name":"","species":"Cat","age":-1}'
-
-# Update a pet
-curl -X PUT http://localhost:5265/api/pets/1 \
- -H "Content-Type: application/json" \
- -d '{"name":"Buddy Updated","species":"Dog","age":4}'
-
-# Delete a pet
-curl -X DELETE http://localhost:5265/api/pets/1
-```
-
-**Expected output:**
-
-- All endpoints work with proper dependency injection
-- Validation errors return structured JSON: `{"errors":["Pet name is required","Pet age must be positive"]}`
-- Logging appears in console for all service operations
-
-### 🔍 Viewing Generated Code (Optional)
-
-To see what code the generator creates, add this to your `.csproj` files:
-
-```xml
-
- true
- $(BaseIntermediateOutputPath)Generated
-
-```
-
-Generated files will appear in `obj/Generated/Atc.SourceGenerators/`:
-
-- `RegistrationAttribute.g.cs` - The `[Registration]` attribute definition
-- `ServiceCollectionExtensions.g.cs` - The `AddDependencyRegistrationsFrom...()` method
-
-### 🎯 Key Takeaways
-
-This quick guide demonstrated:
-
-✅ **Zero boilerplate** - No manual `services.AddScoped()` calls
-✅ **Type safety** - Compile-time validation of registrations
-✅ **Auto-detection** - Automatically registers against implemented interfaces
-✅ **Multi-project support** - Each assembly gets its own registration method
-✅ **Flexible lifetimes** - Singleton, Scoped, and Transient support
-✅ **Clean architecture** - Clear separation between layers
-
-Compare this to manual registration:
-
-```csharp
-// ❌ Without Source Generator (manual, error-prone)
-builder.Services.AddScoped();
-builder.Services.AddScoped();
-builder.Services.AddSingleton();
-builder.Services.AddSingleton();
-// ... and so on for every service
-
-// ✅ With Source Generator (automatic, type-safe, smart naming)
-builder.Services.AddDependencyRegistrationsFromDataAccess();
-builder.Services.AddDependencyRegistrationsFromDomain();
-builder.Services.AddDependencyRegistrationsFromApi();
-```
-
----
-
-## 📦 Installation
-
-Add the NuGet package to each project that contains services to register:
-
-**Required:**
-
-```bash
-dotnet add package Atc.SourceGenerators
-```
-
-**Optional (recommended for better IntelliSense):**
-
-```bash
-dotnet add package Atc.SourceGenerators.Annotations
-```
-
-Or add to your `.csproj` file:
-
-```xml
-
-
-
-
-
-
-
-```
-
-**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);CS0436`
-
-The generator runs at compile time and has zero runtime overhead.
-
----
-
-## 💡 Basic Usage
-
-### 1️⃣ Add Using Directives
-
-```csharp
-using Atc.DependencyInjection;
-```
-
-### 2️⃣ Decorate Your Services
-
-```csharp
-// Simple registration with default singleton lifetime
-[Registration]
-public class CacheService
-{
- public void Store(string key, string value) { }
-}
-
-// Interface auto-detection
-[Registration]
-public class UserService : IUserService
-{
- public void CreateUser(string name) { }
-}
-
-// Scoped lifetime
-[Registration(Lifetime.Scoped)]
-public class OrderService : IOrderService
-{
- public void ProcessOrder(int orderId) { }
-}
-
-// Transient lifetime
-[Registration(Lifetime.Transient)]
-public class LoggerService
-{
- public void Log(string message) { }
-}
-```
-
-### 3️⃣ Register in DI Container
-
-```csharp
-using Microsoft.Extensions.DependencyInjection;
-
-var services = new ServiceCollection();
-
-// Call the generated extension method
-services.AddDependencyRegistrationsFromYourAssemblyName();
-
-var serviceProvider = services.BuildServiceProvider();
-```
-
----
-
-## ✨ Features
-
-- **Automatic Service Registration**: Decorate classes with `[Registration]` attribute for automatic DI registration
-- **Generic Interface Registration**: Full support for open generic types like `IRepository` and `IHandler` 🆕
-- **Keyed Service Registration**: Multiple implementations of the same interface with different keys (.NET 8+)
-- **Factory Method Registration**: Custom initialization logic via static factory methods
-- **TryAdd* Registration**: Conditional registration for default implementations (library pattern)
-- **Conditional Registration**: Register services based on configuration values (feature flags, environment-specific services) 🆕
-- **Assembly Scanning Filters**: Exclude types by namespace, pattern (wildcards), or interface implementation
-- **Runtime Filtering**: Exclude services at registration time with method parameters (different apps, different service subsets) 🆕
-- **Hosted Service Support**: Automatically detects `BackgroundService` and `IHostedService` implementations and uses `AddHostedService()`
-- **Interface Auto-Detection**: Automatically registers against all implemented interfaces (no `As` parameter needed!)
-- **Smart Filtering**: System interfaces (IDisposable, etc.) are automatically excluded
-- **Multiple Interface Support**: Services implementing multiple interfaces are registered against all of them
-- **Flexible Lifetimes**: Support for Singleton, Scoped, and Transient service lifetimes
-- **Explicit Override**: Optional `As` parameter to override auto-detection when needed
-- **Dual Registration**: Register services as both interface and concrete type with `AsSelf`
-- **Compile-time Validation**: Diagnostics for common errors (invalid interface types, missing implementations, incorrect hosted service lifetimes)
-- **Zero Runtime Overhead**: All code is generated at compile time
-- **Native AOT Compatible**: No reflection or runtime code generation - fully trimming-safe and AOT-ready
-- **Multi-Project Support**: Each project generates its own registration method
-
----
-
-## 🏗️ Multi-Project Setup
-
-When using the generator across multiple projects, each project generates its own extension method with a unique name based on the assembly name.
-
-### 📁 Example Structure
-
-```text
-Solution/
-├── MyApp.Api/ → AddDependencyRegistrationsFromApi()
-├── MyApp.Domain/ → AddDependencyRegistrationsFromDomain()
-└── MyApp.DataAccess/ → AddDependencyRegistrationsFromDataAccess()
-```
-
-### ⚡ Program.cs Registration
-
-**Scenario A - Manual Registration (Traditional):**
-
-Call all registration methods explicitly in your startup:
-
-```csharp
-var builder = WebApplication.CreateBuilder(args);
-
-// Register services from all projects manually
-builder.Services.AddDependencyRegistrationsFromDataAccess();
-builder.Services.AddDependencyRegistrationsFromDomain();
-builder.Services.AddDependencyRegistrationsFromApi();
-
-var app = builder.Build();
-```
-
-**Scenario B - Transitive Registration (Recommended):**
-
-Let the generator automatically register services from referenced assemblies:
-
-```csharp
-var builder = WebApplication.CreateBuilder(args);
-
-// Single call automatically registers:
-// - Services from MyApp.Domain
-// - Services from MyApp.DataAccess (referenced by Domain)
-builder.Services.AddDependencyRegistrationsFromDomain(includeReferencedAssemblies: true);
-
-var app = builder.Build();
-```
-
-### 🔄 Transitive Dependency Registration
-
-Each generated registration method has **4 overloads** to support different registration scenarios:
-
-```csharp
-// Overload 1: Default (no transitive registration)
-builder.Services.AddDependencyRegistrationsFromDomain();
-
-// Overload 2: Auto-detect ALL referenced assemblies recursively
-builder.Services.AddDependencyRegistrationsFromDomain(includeReferencedAssemblies: true);
-
-// Overload 3: Register specific referenced assembly by name (short or full name)
-builder.Services.AddDependencyRegistrationsFromDomain("DataAccess");
-builder.Services.AddDependencyRegistrationsFromDomain("MyApp.DataAccess");
-
-// Overload 4: Register multiple specific referenced assemblies
-builder.Services.AddDependencyRegistrationsFromDomain("DataAccess", "Infrastructure");
-```
-
-**How It Works:**
-
-1. **Auto-detect mode** (`includeReferencedAssemblies: true`):
- - Scans ALL referenced assemblies that contain `[Registration]` attributes
- - Recursively registers services from the entire dependency chain
- - Example: Domain → DataAccess → Infrastructure (all registered with ONE call)
-
-2. **Manual mode** (assembly name parameters):
- - Only registers assemblies with matching prefix (e.g., "MyApp.*")
- - Supports both full names ("MyApp.DataAccess") and short names ("DataAccess")
- - Allows fine-grained control over which assemblies to include
-
-3. **Silent skip**:
- - If a specified assembly doesn't exist or has no registrations, it's silently skipped
- - No compile-time or runtime errors
-
-**Benefits:**
-
-✅ **Clean Architecture**: Api → Domain → DataAccess (no need for Api to reference DataAccess directly)
-✅ **Less Boilerplate**: One registration call instead of many
-✅ **Maintainable**: Adding new projects doesn't require updating Program.cs
-✅ **Type-Safe**: All registrations validated at compile time
-
-### 🏷️ Method Naming Convention
-
-The generator creates extension methods based on assembly names with **smart naming**:
-
-| Assembly Name | Smart Naming Result |
-|---------------|---------------------|
-| `PetStore.Domain` (unique suffix) | `AddDependencyRegistrationsFromDomain()` |
-| `PetStore.DataAccess` (unique suffix) | `AddDependencyRegistrationsFromDataAccess()` |
-| `PetStore.Domain` + `AnotherApp.Domain` | `AddDependencyRegistrationsFromPetStoreDomain()` and `AddDependencyRegistrationsFromAnotherAppDomain()` |
-
-Assembly names are sanitized to create valid C# identifiers (dots, dashes, spaces removed).
-
-### ✨ Smart Naming
-
-The generator uses **smart suffix-based naming** to create cleaner, more readable method names:
-
-**How it works:**
-
-- ✅ If the assembly suffix (last segment after final dot) is **unique** among all assemblies → use short suffix
-- ⚠️ If multiple assemblies have the **same suffix** → use full sanitized name to avoid conflicts
-
-**Examples:**
-
-```csharp
-// ✅ Unique suffixes (cleaner names)
-PetStore.Domain → AddDependencyRegistrationsFromDomain()
-PetStore.DataAccess → AddDependencyRegistrationsFromDataAccess()
-PetStore.Api → AddDependencyRegistrationsFromApi()
-
-// ⚠️ Conflicting suffixes (full names prevent collisions)
-PetStore.Domain → AddDependencyRegistrationsFromPetStoreDomain()
-AnotherApp.Domain → AddDependencyRegistrationsFromAnotherAppDomain()
-```
-
-**Benefits:**
-
-- 🎯 **Cleaner API**: Shorter method names when there are no conflicts
-- 🛡️ **Automatic Conflict Prevention**: Fallback to full names prevents naming collisions
-- ⚡ **Zero Configuration**: Works automatically based on compilation context
-- 🔄 **Context-Aware**: Method names adapt to the assemblies in your solution
-
----
-
-## 🔍 Auto-Detection
-
-The generator automatically detects and registers services against their implemented interfaces:
-
-### 1️⃣ Single Interface
-
-```csharp
-public interface IUserService { }
-
-[Registration]
-public class UserService : IUserService { }
-```
-
-**Generated:**
-
-```csharp
-services.AddSingleton();
-```
-
-### 🔢 Multiple Interfaces
-
-```csharp
-public interface IEmailService { }
-public interface INotificationService { }
-
-[Registration]
-public class EmailService : IEmailService, INotificationService { }
-```
-
-**Generated:**
-
-```csharp
-services.AddSingleton();
-services.AddSingleton();
-```
-
-### 🧹 System Interfaces Filtered
-
-System and Microsoft namespace interfaces are automatically excluded:
-
-```csharp
-[Registration]
-public class CacheService : IDisposable
-{
- public void Dispose() { }
-}
-```
-
-**Generated:**
-
-```csharp
-services.AddSingleton(); // IDisposable ignored
-```
-
-### 🎯 Explicit Override
-
-Use `As` parameter to register against a specific interface only:
-
-```csharp
-[Registration(As = typeof(IUserService))]
-public class UserService : IUserService, INotificationService { }
-```
-
-**Generated:**
-
-```csharp
-services.AddSingleton(); // Only IUserService
-```
-
-### 🔀 Register As Both Interface and Concrete Type
-
-Use `AsSelf = true` to register both ways:
-
-```csharp
-[Registration(AsSelf = true)]
-public class EmailService : IEmailService { }
-```
-
-**Generated:**
-
-```csharp
-services.AddSingleton();
-services.AddSingleton();
-```
-
----
-
-## ⏱️ Service Lifetimes
-
-### 🔒 Singleton (Default)
-
-Single instance for the entire application lifetime:
-
-```csharp
-[Registration] // or [Registration(Lifetime.Singleton)]
-public class CacheService { }
-```
-
-**Use for:** Stateless services, shared state, expensive-to-create objects
-
-### 🔄 Scoped
-
-New instance per scope (e.g., per HTTP request):
-
-```csharp
-[Registration(Lifetime.Scoped)]
-public class OrderService : IOrderService { }
-```
-
-**Use for:** Database contexts, request-specific services, unit of work pattern
-
-### ⚡ Transient
-
-New instance every time it's requested:
-
-```csharp
-[Registration(Lifetime.Transient)]
-public class LoggerService { }
-```
-
-**Use for:** Lightweight, stateless services, services that shouldn't be shared
-
----
-
-## 🚀 Native AOT Compatibility
-
-The Dependency Registration Generator is **fully compatible with Native AOT** compilation, making it ideal for modern .NET applications that require fast startup times and minimal deployment sizes.
-
-### ✅ Why It Works
-
-All registration code is generated at compile time with **no reflection or runtime code generation**:
-
-```csharp
-// Your attributed service
-[Registration(Lifetime.Scoped)]
-public class UserService : IUserService { }
-
-// Generated code (compile-time, no reflection!)
-public static class DependencyRegistrationExtensions
-{
- public static IServiceCollection AddDependencyRegistrationsFromApp(
- this IServiceCollection services)
- {
- services.AddScoped();
- return services;
- }
-}
-```
-
-### 🎯 Key Benefits
-
-- **✅ No reflection required**: All service registration happens through direct method calls
-- **✅ Fully trimming-safe**: No dynamic code means the trimmer can safely remove unused code
-- **✅ AOT-ready**: All dependencies are resolved at compile time
-- **✅ Faster startup**: No runtime scanning or reflection overhead
-- **✅ Smaller deployments**: Dead code elimination works perfectly
-- **✅ Better performance**: Native code execution with zero runtime overhead
-
-### 🚀 Native AOT Example
-
-```xml
-
-
- true
-
-
-
-
-
-```
-
-```csharp
-// Your services work seamlessly with Native AOT
-[Registration(Lifetime.Singleton)]
-public class CacheService : ICacheService { }
-
-[Registration(Lifetime.Scoped)]
-public class UserService : IUserService { }
-
-// Program.cs
-var builder = WebApplication.CreateSlimBuilder(args);
-builder.Services.AddDependencyRegistrationsFromApp();
-var app = builder.Build();
-```
-
-**Result:** Fast startup, minimal memory footprint, and production-ready native binaries.
-
----
-
-## ⚙️ RegistrationAttribute Parameters
-
-| Parameter | Type | Default | Description |
-|-----------|------|---------|-------------|
-| `lifetime` | `Lifetime` | `Singleton` | Service lifetime (Singleton, Scoped, or Transient) |
-| `As` | `Type?` | `null` | Explicit interface type to register against (overrides auto-detection) |
-| `AsSelf` | `bool` | `false` | Also register the concrete type when interfaces are detected/specified |
-| `Key` | `object?` | `null` | Service key for keyed service registration (.NET 8+) |
-| `Factory` | `string?` | `null` | Name of static factory method for custom initialization |
-| `TryAdd` | `bool` | `false` | Use TryAdd* methods for conditional registration (library pattern) |
-| `Decorator` | `bool` | `false` | Mark this service as a decorator that wraps the previous registration of the same interface |
-| `Condition` | `string?` | `null` | Configuration key path for conditional registration (feature flags). Prefix with "!" for negation |
-
-### 📝 Examples
-
-```csharp
-// Default singleton, auto-detect interfaces
-[Registration]
-
-// Explicit lifetime
-[Registration(Lifetime.Scoped)]
-
-// Explicit interface
-[Registration(As = typeof(IUserService))]
-
-// Combination
-[Registration(Lifetime.Transient, As = typeof(ILogger))]
-
-// Also register concrete type
-[Registration(AsSelf = true)]
-
-// Keyed service
-[Registration(Key = "Primary", As = typeof(ICache))]
-
-// Factory method
-[Registration(Factory = nameof(Create))]
-
-// TryAdd registration
-[Registration(TryAdd = true)]
-
-// Decorator pattern
-[Registration(Lifetime.Scoped, As = typeof(IOrderService), Decorator = true)]
-
-// Conditional registration
-[Registration(As = typeof(ICache), Condition = "Features:UseRedisCache")]
-
-// Negated conditional
-[Registration(As = typeof(ICache), Condition = "!Features:UseRedisCache")]
-
-// All parameters
-[Registration(Lifetime.Scoped, As = typeof(IService), AsSelf = true, TryAdd = true)]
-```
-
----
-
-## 🛡️ Diagnostics
-
-The generator provides compile-time diagnostics to catch common errors:
-
-### ❌ ATCDIR001: As Type Must Be Interface or Abstract Class
-
-**Severity:** Error
-
-**Description:** The type specified in `As` parameter must be an interface or abstract class.
-
-```csharp
-// ❌ Error: BaseService is a concrete class
-public class BaseService { }
-
-[Registration(As = typeof(BaseService))]
-public class UserService : BaseService { }
-
-// ✅ OK: Abstract base class
-public abstract class AbstractBaseService { }
-
-[Registration(As = typeof(AbstractBaseService))]
-public class UserService : AbstractBaseService { }
-
-// ✅ OK: Interface
-public interface IUserService { }
-
-[Registration(As = typeof(IUserService))]
-public class UserService : IUserService { }
-```
-
-**Fix:** Use an interface, abstract class, or remove the `As` parameter.
-
-### ❌ ATCDIR002: Class Does Not Implement Interface or Inherit Abstract Class
-
-**Severity:** Error
-
-**Description:** Class does not implement the interface or inherit from the abstract class specified in `As` parameter.
-
-```csharp
-public interface IUserService { }
-
-// ❌ Error: UserService doesn't implement IUserService
-[Registration(As = typeof(IUserService))]
-public class UserService { }
-
-public abstract class AuthenticationStateProvider { }
-
-// ❌ Error: UserService doesn't inherit from AuthenticationStateProvider
-[Registration(As = typeof(AuthenticationStateProvider))]
-public class UserService { }
-```
-
-**Fix:** Implement the interface, inherit from the abstract class, or remove the `As` parameter.
-
-### ⚠️ ATCDIR003: Duplicate Registration with Different Lifetime
-
-**Severity:** Warning
-
-**Description:** Service is registered multiple times with different lifetimes.
-
-```csharp
-public interface IUserService { }
-
-// ⚠️ Warning: Same interface registered with two different lifetimes
-[Registration(Lifetime.Singleton)]
-public class UserServiceSingleton : IUserService { }
-
-[Registration(Lifetime.Scoped)]
-public class UserServiceScoped : IUserService { }
-```
-
-**Fix:** Ensure consistent lifetimes or use different interfaces.
-
-### ❌ ATCDIR004: Hosted Services Must Use Singleton Lifetime
-
-**Severity:** Error
-
-**Description:** Hosted services (BackgroundService or IHostedService implementations) must use Singleton lifetime.
-
-```csharp
-// ❌ Error: Hosted services cannot use Scoped or Transient lifetime
-[Registration(Lifetime.Scoped)]
-public class MyBackgroundService : BackgroundService
-{
- protected override Task ExecuteAsync(CancellationToken stoppingToken)
- {
- return Task.CompletedTask;
- }
-}
-```
-
-**Fix:** Use Singleton lifetime (or default [Registration]) for hosted services:
-
-```csharp
-// ✅ Correct: Singleton lifetime (explicit)
-[Registration(Lifetime.Singleton)]
-public class MyBackgroundService : BackgroundService { }
-
-// ✅ Correct: Default lifetime is Singleton
-[Registration]
-public class MyBackgroundService : BackgroundService { }
-```
-
-**Generated Registration:**
-
-```csharp
-services.AddHostedService();
-```
-
----
-
-## 🔷 Generic Interface Registration
-
-The generator supports open generic types, enabling the repository pattern and other generic service patterns.
-
-### Single Type Parameter
-
-```csharp
-// Generic interface
-public interface IRepository where T : class
-{
- T? GetById(int id);
- IEnumerable GetAll();
- void Add(T entity);
-}
-
-// Generic implementation
-[Registration(Lifetime.Scoped)]
-public class Repository : IRepository where T : class
-{
- public T? GetById(int id) => /* implementation */;
- public IEnumerable GetAll() => /* implementation */;
- public void Add(T entity) => /* implementation */;
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
-```
-
-**Usage:**
-
-```csharp
-// Resolve for specific types
-var userRepository = serviceProvider.GetRequiredService>();
-var productRepository = serviceProvider.GetRequiredService>();
-```
-
-### Multiple Type Parameters
-
-```csharp
-// Handler interface with two type parameters
-public interface IHandler
-{
- TResponse Handle(TRequest request);
-}
-
-[Registration(Lifetime.Transient)]
-public class Handler : IHandler
-{
- public TResponse Handle(TRequest request) => /* implementation */;
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddTransient(typeof(IHandler<,>), typeof(Handler<,>));
-```
-
-### Complex Constraints
-
-```csharp
-// Interface with multiple constraints
-public interface IRepository
- where T : class, IEntity, new()
-{
- T Create();
- void Save(T entity);
-}
-
-[Registration(Lifetime.Scoped)]
-public class Repository : IRepository
- where T : class, IEntity, new()
-{
- public T Create() => new T();
- public void Save(T entity) => /* implementation */;
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
-```
-
-### Explicit Generic Registration
-
-You can also use explicit `As` parameter with open generic types:
-
-```csharp
-[Registration(Lifetime.Scoped, As = typeof(IRepository<>))]
-public class Repository : IRepository where T : class
-{
- // Implementation
-}
-```
-
----
-
-## 🔑 Keyed Service Registration
-
-Register multiple implementations of the same interface and resolve them by key (.NET 8+).
-
-### String Keys
-
-```csharp
-[Registration(Lifetime.Scoped, As = typeof(IPaymentProcessor), Key = "Stripe")]
-public class StripePaymentProcessor : IPaymentProcessor
-{
- public Task ProcessPaymentAsync(decimal amount) { /* Stripe implementation */ }
-}
-
-[Registration(Lifetime.Scoped, As = typeof(IPaymentProcessor), Key = "PayPal")]
-public class PayPalPaymentProcessor : IPaymentProcessor
-{
- public Task ProcessPaymentAsync(decimal amount) { /* PayPal implementation */ }
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddKeyedScoped("Stripe");
-services.AddKeyedScoped("PayPal");
-```
-
-**Usage:**
-
-```csharp
-// Constructor injection with [FromKeyedServices]
-public class CheckoutService(
- [FromKeyedServices("Stripe")] IPaymentProcessor stripeProcessor,
- [FromKeyedServices("PayPal")] IPaymentProcessor paypalProcessor)
-{
- // Use specific implementations
-}
-
-// Manual resolution
-var stripeProcessor = serviceProvider.GetRequiredKeyedService("Stripe");
-var paypalProcessor = serviceProvider.GetRequiredKeyedService("PayPal");
-```
-
-### Generic Keyed Services
-
-Keyed services work with generic types:
-
-```csharp
-[Registration(Lifetime.Scoped, As = typeof(IRepository<>), Key = "Primary")]
-public class PrimaryRepository : IRepository where T : class
-{
- public T? GetById(int id) => /* Primary database */;
-}
-
-[Registration(Lifetime.Scoped, As = typeof(IRepository<>), Key = "ReadOnly")]
-public class ReadOnlyRepository : IRepository where T : class
-{
- public T? GetById(int id) => /* Read-only replica */;
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddKeyedScoped(typeof(IRepository<>), "Primary", typeof(PrimaryRepository<>));
-services.AddKeyedScoped(typeof(IRepository<>), "ReadOnly", typeof(ReadOnlyRepository<>));
-```
-
----
-
-## 🏭 Factory Method Registration
-
-Factory methods allow custom initialization logic for services that require configuration values, conditional setup, or complex dependencies.
-
-### Basic Factory Method
-
-```csharp
-[Registration(Lifetime.Scoped, As = typeof(IEmailSender), Factory = nameof(CreateEmailSender))]
-public class EmailSender : IEmailSender
-{
- private readonly string smtpHost;
- private readonly int smtpPort;
-
- private EmailSender(string smtpHost, int smtpPort)
- {
- this.smtpHost = smtpHost;
- this.smtpPort = smtpPort;
- }
-
- public Task SendEmailAsync(string to, string subject, string body)
- {
- // Implementation...
- }
-
- ///
- /// Factory method for creating EmailSender instances.
- /// Must be static and accept IServiceProvider as parameter.
- ///
- public static IEmailSender CreateEmailSender(IServiceProvider serviceProvider)
- {
- // Resolve configuration from DI container
- var config = serviceProvider.GetRequiredService();
- var smtpHost = config["Email:SmtpHost"] ?? "smtp.example.com";
- var smtpPort = int.Parse(config["Email:SmtpPort"] ?? "587");
-
- return new EmailSender(smtpHost, smtpPort);
- }
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddScoped(sp => EmailSender.CreateEmailSender(sp));
-```
-
-### Factory Method Requirements
-
-- ✅ Must be `static`
-- ✅ Must accept `IServiceProvider` as the single parameter
-- ✅ Must return the service type (interface specified in `As` parameter, or class type if no `As` specified)
-- ✅ Can be `public`, `internal`, or `private`
-
-### Factory Method with Multiple Interfaces
-
-```csharp
-[Registration(Lifetime.Singleton, Factory = nameof(CreateService))]
-public class CacheService : ICacheService, IHealthCheck
-{
- private readonly string connectionString;
-
- private CacheService(string connectionString)
- {
- this.connectionString = connectionString;
- }
-
- public static ICacheService CreateService(IServiceProvider sp)
- {
- var config = sp.GetRequiredService();
- var connString = config.GetConnectionString("Redis");
- return new CacheService(connString);
- }
-
- // ICacheService members...
- // IHealthCheck members...
-}
-```
-
-**Generated Code:**
-
-```csharp
-// Registers against both interfaces using the same factory
-services.AddSingleton(sp => CacheService.CreateService(sp));
-services.AddSingleton(sp => CacheService.CreateService(sp));
-```
-
-### Factory Method Best Practices
-
-**When to Use Factory Methods:**
-
-- ✅ Service requires configuration values from `IConfiguration`
-- ✅ Conditional initialization based on runtime environment
-- ✅ Complex dependency resolution beyond constructor injection
-- ✅ Services with private constructors that require initialization
-
-**When NOT to Use Factory Methods:**
-
-- ❌ Simple services with no special initialization - use regular constructor injection
-- ❌ Services that can use `IOptions` pattern instead
-- ❌ When factory logic is overly complex - consider using a dedicated factory class
-
-### Factory Method Diagnostics
-
-The generator provides compile-time validation:
-
-**ATCDIR005: Factory method not found**
-
-```csharp
-// ❌ Error: Factory method doesn't exist
-[Registration(Factory = "NonExistentMethod")]
-public class MyService : IMyService { }
-```
-
-**ATCDIR006: Invalid factory method signature**
-
-```csharp
-// ❌ Error: Factory method must be static
-[Registration(Factory = nameof(Create))]
-public class MyService : IMyService
-{
- public IMyService Create(IServiceProvider sp) => this; // Not static!
-}
-
-// ❌ Error: Wrong parameter type
-public static IMyService Create(string config) => new MyService();
-
-// ❌ Error: Wrong return type
-public static string Create(IServiceProvider sp) => "wrong";
-```
-
-**Correct signature:**
-
-```csharp
-// ✅ Correct: static, accepts IServiceProvider, returns service type
-public static IMyService Create(IServiceProvider sp) => new MyService();
-```
-
----
-
-## 📦 Instance Registration
-
-Instance registration allows you to register pre-created singleton instances via static fields, properties, or methods. This is ideal for immutable configuration objects or singleton instances that are initialized at startup.
-
-### Basic Instance Registration (Static Field)
-
-```csharp
-[Registration(As = typeof(IAppConfiguration), Instance = nameof(DefaultInstance))]
-public class AppConfiguration : IAppConfiguration
-{
- // Static field providing the pre-created instance
- public static readonly AppConfiguration DefaultInstance = new()
- {
- ApplicationName = "My Application",
- Environment = "Production",
- MaxConnections = 100,
- IsDebugMode = false,
- };
-
- // Private constructor enforces singleton pattern
- private AppConfiguration() { }
-
- public string ApplicationName { get; init; } = string.Empty;
- public string Environment { get; init; } = string.Empty;
- public int MaxConnections { get; init; }
- public bool IsDebugMode { get; init; }
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddSingleton(AppConfiguration.DefaultInstance);
-```
-
-### Instance Registration with Static Property
-
-```csharp
-[Registration(As = typeof(ICache), Instance = nameof(Instance))]
-public class MemoryCache : ICache
-{
- // Static property providing the singleton instance
- public static MemoryCache Instance { get; } = new MemoryCache();
-
- private MemoryCache() { }
-
- public void Set(string key, object value) { /* implementation */ }
- public object? Get(string key) { /* implementation */ }
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddSingleton(MemoryCache.Instance);
-```
-
-### Instance Registration with Static Method
-
-```csharp
-[Registration(As = typeof(ILogger), Instance = nameof(GetDefaultLogger))]
-public class DefaultLogger : ILogger
-{
- private static readonly DefaultLogger instance = new();
-
- private DefaultLogger() { }
-
- // Static method returning the singleton instance
- public static DefaultLogger GetDefaultLogger() => instance;
-
- public void Log(string message) => Console.WriteLine($"[{DateTime.UtcNow:O}] {message}");
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.AddSingleton(DefaultLogger.GetDefaultLogger());
-```
-
-### Instance Registration Requirements
-
-- ✅ The `Instance` parameter must reference a **static** field, property, or parameterless method
-- ✅ Instance registration **requires Singleton lifetime** (enforced at compile-time)
-- ✅ The member can be `public`, `internal`, or `private`
-- ✅ Works with `TryAdd`: `services.TryAddSingleton(ClassName.Instance)`
-- ❌ **Cannot** be used with `Factory` parameter (mutually exclusive)
-- ❌ **Cannot** be used with Scoped or Transient lifetimes
-
-### Instance Registration with Multiple Interfaces
-
-When a class implements multiple interfaces, the same instance is registered for each interface:
-
-```csharp
-[Registration(Instance = nameof(DefaultInstance))]
-public class ServiceHub : IServiceA, IServiceB, IHealthCheck
-{
- public static readonly ServiceHub DefaultInstance = new();
-
- private ServiceHub() { }
-
- // IServiceA members...
- // IServiceB members...
- // IHealthCheck members...
-}
-```
-
-**Generated Code:**
-
-```csharp
-// Same instance registered for all interfaces
-services.AddSingleton(ServiceHub.DefaultInstance);
-services.AddSingleton(ServiceHub.DefaultInstance);
-services.AddSingleton(ServiceHub.DefaultInstance);
-```
-
-### Instance Registration Best Practices
-
-**When to Use Instance Registration:**
-
-- ✅ Immutable configuration objects with default values
-- ✅ Pre-initialized singleton services (caches, registries, etc.)
-- ✅ Singleton instances that should be shared across the application
-- ✅ Services with complex initialization that should happen once at startup
-
-**When NOT to Use Instance Registration:**
-
-- ❌ Services that need different instances per scope/request - use factory methods instead
-- ❌ Services requiring runtime configuration - use `IOptions` pattern or factory methods
-- ❌ Services with mutable state that shouldn't be shared
-- ❌ Non-singleton lifetimes - instance registration only supports Singleton
-
-### Instance Registration Diagnostics
-
-The generator provides compile-time validation:
-
-**❌ ATCDIR007: Instance member not found**
-
-```csharp
-[Registration(As = typeof(ICache), Instance = "NonExistentMember")]
-public class CacheService : ICache { }
-// Error: Member 'NonExistentMember' not found. Must be a static field, property, or method.
-```
-
-**❌ ATCDIR008: Instance member must be static**
-
-```csharp
-[Registration(As = typeof(ICache), Instance = nameof(InstanceField))]
-public class CacheService : ICache
-{
- public readonly CacheService InstanceField = new(); // Not static!
-}
-// Error: Instance member 'InstanceField' must be static.
-```
-
-**❌ ATCDIR009: Instance and Factory are mutually exclusive**
-
-```csharp
-[Registration(
- As = typeof(IEmailSender),
- Factory = nameof(Create),
- Instance = nameof(DefaultInstance))] // Cannot use both!
-public class EmailSender : IEmailSender { }
-// Error: Cannot use both Instance and Factory parameters on the same service.
-```
-
-**❌ ATCDIR010: Instance registration requires Singleton lifetime**
-
-```csharp
-[Registration(Lifetime.Scoped, As = typeof(ICache), Instance = nameof(Instance))]
-public class CacheService : ICache
-{
- public static CacheService Instance { get; } = new();
-}
-// Error: Instance registration can only be used with Singleton lifetime. Current lifetime is 'Scoped'.
-```
-
-### Instance vs Factory Method
-
-**Use Instance when:**
-
-- The instance is pre-created and immutable
-- No runtime dependencies or configuration needed
-- Singleton pattern with guaranteed single instance
-
-**Use Factory Method when:**
-
-- Service requires `IServiceProvider` to resolve dependencies
-- Runtime configuration is needed (from `IConfiguration`, environment, etc.)
-- Conditional initialization based on runtime state
-
-**Example comparison:**
-
-```csharp
-// Instance: Pre-created, immutable configuration
-[Registration(As = typeof(IAppSettings), Instance = nameof(Default))]
-public class AppSettings : IAppSettings
-{
- public static readonly AppSettings Default = new() { Timeout = 30 };
-}
-
-// Factory: Runtime configuration from IConfiguration
-[Registration(Lifetime.Singleton, As = typeof(IEmailClient), Factory = nameof(Create))]
-public class EmailClient : IEmailClient
-{
- public static IEmailClient Create(IServiceProvider sp)
- {
- var config = sp.GetRequiredService();
- var apiKey = config["Email:ApiKey"];
- return new EmailClient(apiKey);
- }
-}
-```
-
----
-
-## 🔄 TryAdd* Registration
-
-TryAdd* registration enables conditional service registration that only adds services if they're not already registered. This is particularly useful for library authors who want to provide default implementations that can be easily overridden by application code.
-
-### Basic TryAdd Registration
-
-```csharp
-[Registration(As = typeof(ILogger), TryAdd = true)]
-public class DefaultLogger : ILogger
-{
- public void Log(string message)
- {
- Console.WriteLine($"[DefaultLogger] {message}");
- }
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.TryAddSingleton();
-```
-
-### How TryAdd Works
-
-When `TryAdd = true`, the generator uses `TryAdd{Lifetime}()` methods instead of `Add{Lifetime}()`:
-
-- `TryAddSingleton()` - Only registers if no `T` is already registered
-- `TryAddScoped()` - Only registers if no `T` is already registered
-- `TryAddTransient()` - Only registers if no `T` is already registered
-
-This allows consumers to override default implementations:
-
-```csharp
-// Application code (runs BEFORE library registration)
-services.AddSingleton(); // This takes precedence
-
-// Library registration (uses TryAdd)
-services.AddDependencyRegistrationsFromLibrary();
-// DefaultLogger will NOT be registered because CustomLogger is already registered
-```
-
-### Library Author Pattern
-
-TryAdd is perfect for libraries that want to provide sensible defaults:
-
-```csharp
-// Library code: PetStore.Domain
-namespace PetStore.Domain.Services;
-
-[Registration(Lifetime.Singleton, As = typeof(IHealthCheck), TryAdd = true)]
-public class DefaultHealthCheck : IHealthCheck
-{
- public Task CheckHealthAsync()
- {
- Console.WriteLine("DefaultHealthCheck: Performing basic health check (always healthy)");
- return Task.FromResult(true);
- }
-}
-```
-
-**Consumer can override:**
-
-```csharp
-// Application code
-services.AddSingleton(); // Custom implementation
-services.AddDependencyRegistrationsFromDomain(); // DefaultHealthCheck won't be added
-```
-
-**Or consumer can use default:**
-
-```csharp
-// Application code
-services.AddDependencyRegistrationsFromDomain(); // DefaultHealthCheck is added
-```
-
-### TryAdd with Different Lifetimes
-
-```csharp
-// Scoped with TryAdd
-[Registration(Lifetime.Scoped, As = typeof(ICache), TryAdd = true)]
-public class DefaultCache : ICache
-{
- public string Get(string key) => /* implementation */;
-}
-
-// Transient with TryAdd
-[Registration(Lifetime.Transient, As = typeof(IMessageFormatter), TryAdd = true)]
-public class DefaultMessageFormatter : IMessageFormatter
-{
- public string Format(string message) => /* implementation */;
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.TryAddScoped();
-services.TryAddTransient();
-```
-
-### TryAdd with Factory Methods
-
-TryAdd works seamlessly with factory methods:
-
-```csharp
-[Registration(Lifetime.Singleton, As = typeof(IEmailSender), TryAdd = true, Factory = nameof(CreateEmailSender))]
-public class DefaultEmailSender : IEmailSender
-{
- private readonly string smtpHost;
-
- private DefaultEmailSender(string smtpHost)
- {
- this.smtpHost = smtpHost;
- }
-
- public static IEmailSender CreateEmailSender(IServiceProvider provider)
- {
- var config = provider.GetRequiredService();
- var host = config["Email:SmtpHost"] ?? "localhost";
- return new DefaultEmailSender(host);
- }
-
- public Task SendEmailAsync(string to, string subject, string body)
- {
- // Implementation...
- }
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.TryAddSingleton(sp => DefaultEmailSender.CreateEmailSender(sp));
-```
-
-### TryAdd with Generic Types
-
-TryAdd supports generic interface registration:
-
-```csharp
-[Registration(Lifetime.Scoped, TryAdd = true)]
-public class DefaultRepository : IRepository where T : class
-{
- public T? GetById(int id) => /* implementation */;
- public IEnumerable GetAll() => /* implementation */;
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.TryAddScoped(typeof(IRepository<>), typeof(DefaultRepository<>));
-```
-
-### TryAdd with Multiple Interfaces
-
-When a service implements multiple interfaces, TryAdd is applied to each registration:
-
-```csharp
-[Registration(TryAdd = true)]
-public class DefaultNotificationService : IEmailNotificationService, ISmsNotificationService
-{
- public Task SendEmailAsync(string email, string message) => /* implementation */;
- public Task SendSmsAsync(string phoneNumber, string message) => /* implementation */;
-}
-```
-
-**Generated Code:**
-
-```csharp
-services.TryAddSingleton();
-services.TryAddSingleton();
-```
-
-### TryAdd Best Practices
-
-**When to Use TryAdd:**
-
-- ✅ Library projects providing default implementations
-- ✅ Fallback services that applications may want to customize
-- ✅ Services with sensible defaults but customizable behavior
-- ✅ Avoiding registration conflicts in modular applications
-
-**When NOT to Use TryAdd:**
-
-- ❌ Core application services that should always be registered
-- ❌ Services where registration order matters for business logic
-- ❌ When you need to explicitly override existing registrations (use regular registration)
-
-### Important Notes
-
-**Keyed Services:**
-TryAdd is **not supported** with keyed services. When both `Key` and `TryAdd` are specified, the generator will prioritize keyed registration and ignore `TryAdd`:
-
-```csharp
-// ⚠️ TryAdd is ignored when Key is specified
-[Registration(Key = "Primary", TryAdd = true)]
-public class PrimaryCache : ICache { }
-
-// Generated (keyed registration, no TryAdd):
-services.AddKeyedSingleton("Primary");
-```
-
-**Registration Order:**
-For TryAdd to work correctly, ensure library registrations happen **after** application-specific registrations:
-
-```csharp
-// ✅ Correct order
-services.AddSingleton(); // Application override
-services.AddDependencyRegistrationsFromLibrary(); // Library defaults (TryAdd)
-
-// ❌ Wrong order
-services.AddDependencyRegistrationsFromLibrary(); // Library defaults register first
-services.AddSingleton(); // This creates a duplicate registration!
-```
-
----
-
-## 🚫 Assembly Scanning Filters
-
-Assembly Scanning Filters allow you to exclude specific types, namespaces, or patterns from automatic registration. This is particularly useful for:
-
-- Excluding internal/test services from production builds
-- Preventing mock/stub services from being registered
-- Filtering out utilities that shouldn't be in the DI container
-
-### Basic Filter Usage
-
-Filters are applied using the `[RegistrationFilter]` attribute at the assembly level:
-
-```csharp
-using Atc.DependencyInjection;
-
-// Exclude internal services
-[assembly: RegistrationFilter(ExcludeNamespaces = new[] { "MyApp.Internal" })]
-
-// Your services
-namespace MyApp.Services
-{
- [Registration]
- public class ProductionService : IProductionService { } // ✅ Will be registered
-}
-
-namespace MyApp.Internal
-{
- [Registration]
- public class InternalService : IInternalService { } // ❌ Excluded by filter
-}
-```
-
-### Namespace Exclusion
-
-Exclude types in specific namespaces. Sub-namespaces are also excluded:
-
-```csharp
-[assembly: RegistrationFilter(ExcludeNamespaces = new[] {
- "MyApp.Internal",
- "MyApp.Testing",
- "MyApp.Utilities"
-})]
-
-namespace MyApp.Services
-{
- [Registration]
- public class UserService : IUserService { } // ✅ Registered
-}
-
-namespace MyApp.Internal
-{
- [Registration]
- public class InternalCache : ICache { } // ❌ Excluded
-}
-
-namespace MyApp.Internal.Deep.Nested
-{
- [Registration]
- public class DeepService : IDeepService { } // ❌ Also excluded (sub-namespace)
-}
-```
-
-**How Namespace Filtering Works:**
-
-- Exact match: `"MyApp.Internal"` excludes types in that namespace
-- Sub-namespace match: Also excludes `"MyApp.Internal.Something"`, `"MyApp.Internal.Deep.Nested"`, etc.
-
-### Pattern Exclusion
-
-Exclude types whose names match wildcard patterns. Supports `*` (any characters) and `?` (single character):
-
-```csharp
-[assembly: RegistrationFilter(ExcludePatterns = new[] {
- "*Mock*", // Excludes MockEmailService, EmailMockService, etc.
- "*Test*", // Excludes TestHelper, UserTestService, etc.
- "Temp*", // Excludes TempService, TempCache, etc.
- "Old?Data" // Excludes OldAData, OldBData, but NOT OldAbcData
-})]
-
-namespace MyApp.Services
-{
- [Registration]
- public class ProductionEmailService : IEmailService { } // ✅ Registered
-
- [Registration]
- public class MockEmailService : IEmailService { } // ❌ Excluded (*Mock*)
-
- [Registration]
- public class UserTestHelper : ITestHelper { } // ❌ Excluded (*Test*)
-
- [Registration]
- public class TempCache : ICache { } // ❌ Excluded (Temp*)
-}
-```
-
-**Pattern Matching Rules:**
-
-- `*` matches zero or more characters
-- `?` matches exactly one character
-- Matching is case-insensitive
-- Patterns match against the type name (not the full namespace)
-
-### Interface Exclusion
-
-Exclude types that implement specific interfaces:
-
-```csharp
-[assembly: RegistrationFilter(ExcludeImplementing = new[] {
- typeof(ITestUtility),
- typeof(IInternalTool)
-})]
-
-namespace MyApp.Services
-{
- public interface ITestUtility { }
- public interface IProductionService { }
-
- [Registration]
- public class ProductionService : IProductionService { } // ✅ Registered
-
- [Registration]
- public class TestHelper : ITestUtility { } // ❌ Excluded (implements ITestUtility)
-
- [Registration]
- public class MockDatabase : IDatabase, ITestUtility { } // ❌ Excluded (implements ITestUtility)
-}
-```
-
-**How Interface Filtering Works:**
-
-- Checks all interfaces implemented by the type
-- Uses proper generic type comparison (`SymbolEqualityComparer`)
-- Works with generic interfaces like `IRepository`
-
-### Combining Multiple Filters
-
-You can combine multiple filter types in a single attribute:
-
-```csharp
-[assembly: RegistrationFilter(
- ExcludeNamespaces = new[] { "MyApp.Internal", "MyApp.Testing" },
- ExcludePatterns = new[] { "*Mock*", "*Test*", "*Fake*" },
- ExcludeImplementing = new[] { typeof(ITestUtility) })]
-
-// All filter rules are applied
-// A type is excluded if it matches ANY of the rules
-```
-
-### Multiple Filter Attributes
-
-You can also apply multiple `[RegistrationFilter]` attributes:
-
-```csharp
-// Filter 1: Exclude internal namespaces
-[assembly: RegistrationFilter(ExcludeNamespaces = new[] {
- "MyApp.Internal"
-})]
-
-// Filter 2: Exclude test patterns
-[assembly: RegistrationFilter(ExcludePatterns = new[] {
- "*Mock*",
- "*Test*"
-})]
-
-// Filter 3: Exclude utility interfaces
-[assembly: RegistrationFilter(ExcludeImplementing = new[] {
- typeof(ITestUtility)
-})]
-
-// All filters are combined
-```
-
-### Real-World Example
-
-Here's a complete example showing filters in action:
-
-```csharp
-// AssemblyInfo.cs
-using Atc.DependencyInjection;
-
-[assembly: RegistrationFilter(
- ExcludeNamespaces = new[] {
- "MyApp.Internal",
- "MyApp.Development"
- },
- ExcludePatterns = new[] {
- "*Mock*",
- "*Test*",
- "*Fake*",
- "Temp*"
- })]
-```
-
-```csharp
-// Production service - WILL be registered
-namespace MyApp.Services
-{
- [Registration]
- public class EmailService : IEmailService
- {
- public void SendEmail(string to, string message) { }
- }
-}
-
-// Internal service - EXCLUDED by namespace
-namespace MyApp.Internal
-{
- [Registration]
- public class InternalCache : ICache { } // ❌ Excluded
-}
-
-// Mock service - EXCLUDED by pattern
-namespace MyApp.Services
-{
- [Registration]
- public class MockEmailService : IEmailService { } // ❌ Excluded
-}
-
-// Test helper - EXCLUDED by pattern
-namespace MyApp.Testing
-{
- [Registration]
- public class TestDataBuilder : ITestHelper { } // ❌ Excluded
-}
-```
-
-### Filter Priority and Behavior
-
-**Important Notes:**
-
-1. **Filters are applied first**: Types are filtered OUT before any registration happens
-2. **ANY match excludes**: If a type matches ANY filter rule, it's excluded
-3. **Applies to all registrations**: Filters affect both current assembly and referenced assemblies
-4. **No diagnostics for filtered types**: Filtered types are silently skipped (this is intentional)
-
-### Verification
-
-You can verify filters are working by trying to resolve filtered services:
-
-```csharp
-var services = new ServiceCollection();
-services.AddDependencyRegistrationsFromMyApp();
-
-var provider = services.BuildServiceProvider();
-
-// This will return null (service was filtered out)
-var mockService = provider.GetService();
-Console.WriteLine($"MockEmailService registered: {mockService != null}"); // False
-
-// This will succeed (service was not filtered)
-var emailService = provider.GetRequiredService();
-Console.WriteLine($"EmailService registered: {emailService != null}"); // True
-```
-
-### Best Practices
-
-**When to Use Filters:**
-
-- ✅ Excluding internal implementation details from DI
-- ✅ Preventing test/mock services from production builds
-- ✅ Filtering development-only utilities
-- ✅ Clean separation between production and development code
-
-**When NOT to Use Filters:**
-
-- ❌ Don't use filters as the primary way to control registration (use conditional compilation instead)
-- ❌ Don't create overly complex filter patterns that are hard to understand
-- ❌ Don't filter services that SHOULD be in DI but you forgot to configure properly
-
-**Recommended Patterns:**
-
-```csharp
-// ✅ Good: Clear, specific exclusions
-[assembly: RegistrationFilter(
- ExcludeNamespaces = new[] { "MyApp.Internal" },
- ExcludePatterns = new[] { "*Mock*", "*Test*" })]
-
-// ❌ Avoid: Overly broad patterns
-[assembly: RegistrationFilter(ExcludePatterns = new[] { "*" })] // Excludes everything!
-
-// ❌ Avoid: Filters as primary registration control
-// Instead of filtering, just don't add [Registration] attribute
-```
-
----
-
-## 🎯 Runtime Filtering
-
-Runtime filtering allows you to exclude specific services **when calling** the registration methods, rather than at compile time. This is extremely useful when:
-
-- Different applications need different subsets of services from a shared library
-- You want to exclude services conditionally based on runtime configuration
-- Testing scenarios require specific services to be excluded
-- Multiple applications share the same domain library but have different infrastructure needs
-
-### Basic Usage
-
-All generated `AddDependencyRegistrationsFrom*()` methods support three optional filter parameters:
-
-```csharp
-services.AddDependencyRegistrationsFromDomain(
- excludedNamespaces: new[] { "MyApp.Domain.Internal" },
- excludedPatterns: new[] { "*Test*", "*Mock*" },
- excludedTypes: new[] { typeof(EmailService), typeof(SmsService) });
-```
-
-### 🔹 Filter by Type
-
-Exclude specific types explicitly:
-
-```csharp
-// Exclude specific services by type
-services.AddDependencyRegistrationsFromDomain(
- excludedTypes: new[] { typeof(EmailService), typeof(NotificationService) });
-```
-
-**Example Scenario**: PetStore.Api uses email services, but PetStore.WpfApp doesn't need them:
-
-```csharp
-// PetStore.Api - includes all services
-services.AddDependencyRegistrationsFromDomain();
-
-// PetStore.WpfApp - excludes email/notification services
-services.AddDependencyRegistrationsFromDomain(
- excludedTypes: new[] { typeof(EmailService), typeof(INotificationService) });
-```
-
-### 🔹 Filter by Namespace
-
-Exclude entire namespaces (including sub-namespaces):
-
-```csharp
-// Exclude all services in the Internal namespace
-services.AddDependencyRegistrationsFromDomain(
- excludedNamespaces: new[] { "MyApp.Domain.Internal" });
-
-// Also excludes MyApp.Domain.Internal.Utils, MyApp.Domain.Internal.Deep, etc.
-```
-
-**Example Scenario**: Different deployment environments need different services:
-
-```csharp
-#if PRODUCTION
- // Production: exclude development/debug services
- services.AddDependencyRegistrationsFromDomain(
- excludedNamespaces: new[] { "MyApp.Domain.Development", "MyApp.Domain.Debug" });
-#else
- // Development: include all services
- services.AddDependencyRegistrationsFromDomain();
-#endif
-```
-
-### 🔹 Filter by Pattern
-
-Exclude services using wildcard patterns (`*` = any characters, `?` = single character):
-
-```csharp
-// Exclude all mock, test, and fake services
-services.AddDependencyRegistrationsFromDomain(
- excludedPatterns: new[] { "*Mock*", "*Test*", "*Fake*", "*Stub*" });
-
-// Exclude all services ending with "Helper" or "Utility"
-services.AddDependencyRegistrationsFromDomain(
- excludedPatterns: new[] { "*Helper", "*Utility" });
-```
-
-**Example Scenario**: Exclude all logging services in a minimal deployment:
-
-```csharp
-// Minimal deployment - no logging services
-services.AddDependencyRegistrationsFromDomain(
- excludedPatterns: new[] { "*Logger*", "*Logging*", "*Log*" });
-```
-
-### 🔹 Combining Filters
-
-All three filter types can be used together:
-
-```csharp
-services.AddDependencyRegistrationsFromDomain(
- excludedNamespaces: new[] { "MyApp.Domain.Internal" },
- excludedPatterns: new[] { "*Test*", "*Development*" },
- excludedTypes: new[] { typeof(LegacyService), typeof(DeprecatedFeature) });
-```
-
-### 🔹 Filters with Transitive Registration
-
-Runtime filters are automatically propagated to referenced assemblies:
-
-```csharp
-// Filters apply to Domain AND all referenced assemblies (DataAccess, Infrastructure, etc.)
-services.AddDependencyRegistrationsFromDomain(
- includeReferencedAssemblies: true,
- excludedNamespaces: new[] { "*.Internal" },
- excludedPatterns: new[] { "*Test*" },
- excludedTypes: new[] { typeof(EmailService) });
-```
-
-All referenced assemblies will also exclude:
-
-- Any namespace ending with `.Internal`
-- Any type matching `*Test*` pattern
-- The `EmailService` type
-
-### Runtime vs. Compile-Time Filtering
-
-| Feature | Compile-Time (Assembly) | Runtime (Method Parameters) |
-|---------|------------------------|----------------------------|
-| **Applied When** | During source generation | During service registration |
-| **Scope** | All registrations from assembly | Specific registration call |
-| **Use Case** | Global exclusions (test/mock services) | Application-specific exclusions |
-| **Configured In** | `AssemblyInfo.cs` with `[RegistrationFilter]` | Method call parameters |
-| **Flexibility** | Fixed at compile time | Can vary per application/scenario |
-
-### Complete Example: Multi-Application Scenario
-
-**Shared Domain Library** (PetStore.Domain):
-
-```csharp
-namespace PetStore.Domain.Services;
-
-[Registration]
-public class PetService : IPetService { } // Core service - needed by all apps
-
-[Registration]
-public class EmailService : IEmailService { } // Email - only needed by API
-
-[Registration]
-public class ReportService : IReportService { } // Reports - only needed by Admin
-
-[Registration]
-public class NotificationService : INotificationService { } // Notifications - only API
-```
-
-**PetStore.Api** (Web API - needs email + notifications):
-
-```csharp
-// Include all services
-services.AddDependencyRegistrationsFromDomain();
-```
-
-**PetStore.WpfApp** (Desktop app - needs reports, not email):
-
-```csharp
-// Exclude email and notification services
-services.AddDependencyRegistrationsFromDomain(
- excludedTypes: new[] { typeof(EmailService), typeof(NotificationService) });
-```
-
-**PetStore.AdminPortal** (Admin - needs reports, not notifications):
-
-```csharp
-// Exclude notification services
-services.AddDependencyRegistrationsFromDomain(
- excludedTypes: new[] { typeof(NotificationService) });
-```
-
-**PetStore.MobileApp** (Minimal deployment):
-
-```csharp
-// Exclude email, notifications, and reports
-services.AddDependencyRegistrationsFromDomain(
- excludedTypes: new[]
- {
- typeof(EmailService),
- typeof(NotificationService),
- typeof(ReportService)
- });
-```
-
-### Best Practices
-
-✅ **Do:**
-
-- Use runtime filtering when different applications need different service subsets
-- Use type exclusion for specific services you know by name
-- Use pattern exclusion for groups of services (e.g., all `*Mock*` services)
-- Use namespace exclusion for entire feature areas
-- Combine with compile-time filters for maximum control
-
-```csharp
-// Good: Application-specific exclusions
-services.AddDependencyRegistrationsFromDomain(
- excludedTypes: new[] { typeof(EmailService) }); // This app doesn't send emails
-```
-
-❌ **Avoid:**
-
-- Using overly broad patterns that might accidentally exclude needed services
-- Runtime filtering as a replacement for proper service design
-- Filtering when you should just not add `[Registration]` attribute
-
-```csharp
-// Bad: Overly broad pattern
-services.AddDependencyRegistrationsFromDomain(
- excludedPatterns: new[] { "*Service*" }); // Excludes almost everything!
-
-// Bad: Should use compile-time filtering instead
-services.AddDependencyRegistrationsFromDomain(
- excludedPatterns: new[] { "*Test*" }); // Tests should be excluded at compile time
-```
-
-### Verification
-
-You can verify which services are excluded by inspecting the service collection:
-
-```csharp
-services.AddDependencyRegistrationsFromDomain(
- excludedTypes: new[] { typeof(EmailService) });
-
-// Verify EmailService is not registered
-var emailService = serviceProvider.GetService();
-Console.WriteLine($"EmailService registered: {emailService != null}"); // False
-```
-
----
-
-## 🎨 Decorator Pattern
-
-The decorator pattern allows you to wrap existing services with additional functionality (logging, caching, validation, etc.) without modifying the original implementation. This is perfect for implementing cross-cutting concerns in a clean, maintainable way.
-
-### ✨ How It Works
-
-1. **Register the base service** normally with `[Registration]`
-2. **Create a decorator class** that implements the same interface and wraps the base service
-3. **Mark the decorator** with `[Registration(Decorator = true)]`
-4. The generator automatically:
- - Registers base services first
- - Then registers decorators that wrap them
- - Preserves the service lifetime
-
-### 📝 Basic Example
-
-```csharp
-// Interface
-public interface IOrderService
-{
- Task PlaceOrderAsync(string orderId);
-}
-
-// Base service - registered first
-[Registration(Lifetime.Scoped, As = typeof(IOrderService))]
-public class OrderService : IOrderService
-{
- public Task PlaceOrderAsync(string orderId)
- {
- Console.WriteLine($"[OrderService] Processing order {orderId}");
- return Task.CompletedTask;
- }
-}
-
-// Decorator - wraps the base service
-[Registration(Lifetime.Scoped, As = typeof(IOrderService), Decorator = true)]
-public class LoggingOrderServiceDecorator : IOrderService
-{
- private readonly IOrderService inner;
- private readonly ILogger logger;
-
- // First parameter MUST be the interface being decorated
- public LoggingOrderServiceDecorator(
- IOrderService inner,
- ILogger logger)
- {
- this.inner = inner;
- this.logger = logger;
- }
-
- public async Task PlaceOrderAsync(string orderId)
- {
- logger.LogInformation("Before placing order {OrderId}", orderId);
- await inner.PlaceOrderAsync(orderId);
- logger.LogInformation("After placing order {OrderId}", orderId);
- }
-}
-```
-
-**Usage:**
-
-```csharp
-services.AddDependencyRegistrationsFromDomain();
-
-var orderService = serviceProvider.GetRequiredService();
-await orderService.PlaceOrderAsync("ORDER-123");
-
-// Output:
-// [LoggingDecorator] Before placing order ORDER-123
-// [OrderService] Processing order ORDER-123
-// [LoggingDecorator] After placing order ORDER-123
-```
-
-### Generated Code
-
-The generator creates special `Decorate` extension methods that:
-
-1. Find the existing service registration
-2. Remove it from the service collection
-3. Create a new registration that resolves the original and wraps it
-
-```csharp
-// Generated registration code
-services.AddScoped(); // Base service
-services.Decorate((provider, inner) => // Decorator
-{
- return ActivatorUtilities.CreateInstance(provider, inner);
-});
-```
-
-### 🔄 Multiple Decorators
-
-You can stack multiple decorators - they are applied in the order they are discovered:
-
-```csharp
-[Registration(Lifetime.Scoped, As = typeof(IOrderService))]
-public class OrderService : IOrderService { }
-
-[Registration(Lifetime.Scoped, As = typeof(IOrderService), Decorator = true)]
-public class LoggingDecorator : IOrderService { }
-
-[Registration(Lifetime.Scoped, As = typeof(IOrderService), Decorator = true)]
-public class ValidationDecorator : IOrderService { }
-
-[Registration(Lifetime.Scoped, As = typeof(IOrderService), Decorator = true)]
-public class CachingDecorator : IOrderService { }
-```
-
-**Result:** `CachingDecorator → ValidationDecorator → LoggingDecorator → OrderService`
-
-### 🎯 Common Use Cases
-
-#### 1. Logging/Auditing
-
-```csharp
-[Registration(Decorator = true)]
-public class AuditingDecorator : IPetService
-{
- private readonly IPetService inner;
- private readonly IAuditLog auditLog;
-
- public Pet CreatePet(CreatePetRequest request)
- {
- var result = inner.CreatePet(request);
- auditLog.Log($"Created pet {result.Id} by {currentUser}");
- return result;
- }
-}
-```
-
-#### 2. Caching
-
-```csharp
-[Registration(Decorator = true)]
-public class CachingPetServiceDecorator : IPetService
-{
- private readonly IPetService inner;
- private readonly IMemoryCache cache;
-
- public Pet? GetById(Guid id)
- {
- return cache.GetOrCreate($"pet:{id}", entry =>
- {
- entry.SlidingExpiration = TimeSpan.FromMinutes(5);
- return inner.GetById(id);
- });
- }
-}
-```
-
-#### 3. Validation
-
-```csharp
-[Registration(Decorator = true)]
-public class ValidationDecorator : IPetService
-{
- private readonly IPetService inner;
- private readonly IValidator validator;
-
- public Pet CreatePet(CreatePetRequest request)
- {
- var validationResult = validator.Validate(request);
- if (!validationResult.IsValid)
- {
- throw new ValidationException(validationResult.Errors);
- }
- return inner.CreatePet(request);
- }
-}
-```
-
-#### 4. Retry Logic
-
-```csharp
-[Registration(Decorator = true)]
-public class RetryDecorator : IExternalApiService
-{
- private readonly IExternalApiService inner;
-
- public async Task CallApiAsync()
- {
- for (int i = 0; i < 3; i++)
- {
- try
- {
- return await inner.CallApiAsync();
- }
- catch (HttpRequestException) when (i < 2)
- {
- await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i)));
- }
- }
- }
-}
-```
-
-### ⚠️ Important Notes
-
-1. **Explicit `As` Required**: Decorators MUST specify the `As` parameter to indicate which interface they decorate
-
- ```csharp
- // ❌ Won't work - missing As parameter
- [Registration(Decorator = true)]
- public class MyDecorator : IService { }
-
- // ✅ Correct
- [Registration(As = typeof(IService), Decorator = true)]
- public class MyDecorator : IService { }
- ```
-
-2. **Constructor First Parameter**: The decorator's constructor must accept the interface as the first parameter
-
- ```csharp
- // ✅ Correct - interface is first parameter
- public MyDecorator(IService inner, ILogger logger) { }
-
- // ✅ Also correct - only parameter
- public MyDecorator(IService inner) { }
- ```
-
-3. **Matching Lifetime**: Decorators inherit the lifetime of the base service registration
-
-4. **Registration Order**: Base services are always registered before decorators, regardless of file order
-
-### 🔍 Complete Example
-
-See the **PetStore.Domain** sample for a complete working example:
-
-- Base service: [PetService.cs](../../sample/PetStore.Domain/Services/PetService.cs)
-- Decorator: [LoggingPetServiceDecorator.cs](../../sample/PetStore.Domain/Services/LoggingPetServiceDecorator.cs)
-
----
-
-## 🎛️ Conditional Registration
-
-Conditional Registration allows you to register services based on configuration values at runtime. This is perfect for feature flags, environment-specific services, A/B testing, and gradual rollouts.
-
-### ✨ How It Works
-
-Services with a `Condition` parameter are only registered if the configuration value at the specified key path evaluates to `true`. The condition is checked at runtime when the registration methods are called.
-
-When an assembly contains services with conditional registration:
-
-- An `IConfiguration` parameter is **automatically added** to all generated extension method signatures
-- The configuration value is checked using `configuration.GetValue("key")`
-- Services are registered inside `if` blocks based on the condition
-
-### 📝 Basic Example
-
-```csharp
-// Register RedisCache only when Features:UseRedisCache is true
-[Registration(As = typeof(ICache), Condition = "Features:UseRedisCache")]
-public class RedisCache : ICache
-{
- public string Get(string key) => /* Redis implementation */;
- public void Set(string key, string value) => /* Redis implementation */;
-}
-
-// Register MemoryCache only when Features:UseRedisCache is false
-[Registration(As = typeof(ICache), Condition = "!Features:UseRedisCache")]
-public class MemoryCache : ICache
-{
- public string Get(string key) => /* In-memory implementation */;
- public void Set(string key, string value) => /* In-memory implementation */;
-}
-```
-
-**Configuration (appsettings.json):**
-
-```json
-{
- "Features": {
- "UseRedisCache": true
- }
-}
-```
-
-**Usage:**
-
-```csharp
-var configuration = new ConfigurationBuilder()
- .AddJsonFile("appsettings.json")
- .Build();
-
-// IConfiguration is required when conditional services exist
-services.AddDependencyRegistrationsFromDomain(configuration);
-
-// Resolves to RedisCache (because Features:UseRedisCache = true)
-var cache = serviceProvider.GetRequiredService();
-```
-
-### Generated Code
-
-```csharp
-public static IServiceCollection AddDependencyRegistrationsFromDomain(
- this IServiceCollection services,
- IConfiguration configuration)
-{
- // Conditional registration with positive check
- if (configuration.GetValue("Features:UseRedisCache"))
- {
- services.AddSingleton();
- }
-
- // Conditional registration with negation
- if (!configuration.GetValue("Features:UseRedisCache"))
- {
- services.AddSingleton();
- }
-
- return services;
-}
-```
-
-### 🔄 Negation Support
-
-Prefix the condition with `!` to negate it (register when the value is `false`):
-
-```csharp
-// Register when Features:UseRedisCache is FALSE
-[Registration(As = typeof(ICache), Condition = "!Features:UseRedisCache")]
-public class MemoryCache : ICache { }
-```
-
-**Generated:**
-
-```csharp
-if (!configuration.GetValue("Features:UseRedisCache"))
-{
- services.AddSingleton();
-}
-```
-
-### 🎯 Common Use Cases
-
-#### 1. Feature Flags
-
-Enable/disable features without code changes:
-
-```csharp
-// Premium features only when enabled
-[Registration(Lifetime.Scoped, As = typeof(IPremiumService), Condition = "Features:EnablePremium")]
-public class PremiumService : IPremiumService
-{
- public void ExecutePremiumFeature() { /* Premium logic */ }
-}
-```
-
-**Configuration:**
-
-```json
-{
- "Features": {
- "EnablePremium": true
- }
-}
-```
-
-#### 2. Environment-Specific Services
-
-Different implementations for different environments:
-
-```csharp
-// Production email service
-[Registration(As = typeof(IEmailService), Condition = "Environment:IsProduction")]
-public class SendGridEmailService : IEmailService { }
-
-// Development email service (logs instead of sending)
-[Registration(As = typeof(IEmailService), Condition = "!Environment:IsProduction")]
-public class LoggingEmailService : IEmailService { }
-```
-
-#### 3. A/B Testing
-
-Register different implementations based on experiment configuration:
-
-```csharp
-[Registration(As = typeof(IRecommendationEngine), Condition = "Experiments:UseNewAlgorithm")]
-public class NewRecommendationEngine : IRecommendationEngine { }
-
-[Registration(As = typeof(IRecommendationEngine), Condition = "!Experiments:UseNewAlgorithm")]
-public class LegacyRecommendationEngine : IRecommendationEngine { }
-```
-
-#### 4. Cost Optimization
-
-Disable expensive services when not needed:
-
-```csharp
-// AI service only when enabled (cost-saving)
-[Registration(As = typeof(IAIService), Condition = "Services:EnableAI")]
-public class OpenAIService : IAIService { }
-
-// Fallback simple service
-[Registration(As = typeof(IAIService), Condition = "!Services:EnableAI")]
-public class BasicTextService : IAIService { }
-```
-
-### 🎨 Advanced Scenarios
-
-#### Multiple Conditional Services
-
-```csharp
-[Registration(As = typeof(IStorage), Condition = "Storage:UseAzure")]
-public class AzureBlobStorage : IStorage { }
-
-[Registration(As = typeof(IStorage), Condition = "Storage:UseAWS")]
-public class S3Storage : IStorage { }
-
-[Registration(As = typeof(IStorage), Condition = "Storage:UseLocal")]
-public class LocalFileStorage : IStorage { }
-```
-
-**Configuration:**
-
-```json
-{
- "Storage": {
- "UseAzure": false,
- "UseAWS": true,
- "UseLocal": false
- }
-}
-```
-
-#### Combining with Different Lifetimes
-
-```csharp
-// Scoped Redis cache (production)
-[Registration(Lifetime.Scoped, As = typeof(ICache), Condition = "Cache:UseRedis")]
-public class RedisCache : ICache { }
-
-// Singleton memory cache (development)
-[Registration(Lifetime.Singleton, As = typeof(ICache), Condition = "!Cache:UseRedis")]
-public class MemoryCache : ICache { }
-```
-
-#### Mixing Conditional and Unconditional
-
-```csharp
-// Always registered (core service)
-[Registration(Lifetime.Scoped, As = typeof(IUserService))]
-public class UserService : IUserService { }
-
-// Conditionally registered (optional feature)
-[Registration(Lifetime.Scoped, As = typeof(IAnalyticsService), Condition = "Features:EnableAnalytics")]
-public class AnalyticsService : IAnalyticsService { }
-```
-
-### ⚙️ Configuration Best Practices
-
-**1. Use Hierarchical Configuration Keys:**
-
-```csharp
-// Good: Organized hierarchy
-[Registration(Condition = "Features:Cache:UseRedis")]
-[Registration(Condition = "Features:Email:UseSendGrid")]
-[Registration(Condition = "Experiments:NewUI:Enabled")]
-```
-
-**2. Boolean Values:**
-
-Conditions always use `GetValue()`, so ensure configuration values are boolean:
-
-```json
-{
- "Features": {
- "UseRedisCache": true, // ✅ Correct
- "EnablePremium": "true", // ⚠️ Works but not ideal
- "UseNewAlgorithm": 1 // ❌ Won't work as expected
- }
-}
-```
-
-**3. Default Values:**
-
-If a configuration key is missing, `GetValue()` returns `false` by default:
-
-```csharp
-// If "Features:UseRedisCache" doesn't exist in config, MemoryCache is used
-[Registration(Condition = "Features:UseRedisCache")]
-public class RedisCache : ICache { }
-
-[Registration(Condition = "!Features:UseRedisCache")]
-public class MemoryCache : ICache { } // ← This one is registered (default false)
-```
-
-### 🔍 IConfiguration Parameter Behavior
-
-**Without Conditional Services:**
-
-```csharp
-// No conditional services → no IConfiguration parameter
-services.AddDependencyRegistrationsFromDomain();
-```
-
-**With Conditional Services:**
-
-```csharp
-// Has conditional services → IConfiguration parameter required
-services.AddDependencyRegistrationsFromDomain(configuration);
-```
-
-**All Overloads Updated:**
-
-When conditional services exist, ALL generated overloads include the `IConfiguration` parameter:
-
-```csharp
-// Overload 1: Basic registration
-services.AddDependencyRegistrationsFromDomain(configuration);
-
-// Overload 2: With transitive registration
-services.AddDependencyRegistrationsFromDomain(configuration, includeReferencedAssemblies: true);
-
-// Overload 3: With specific assembly
-services.AddDependencyRegistrationsFromDomain(configuration, "DataAccess");
-
-// Overload 4: With multiple assemblies
-services.AddDependencyRegistrationsFromDomain(configuration, "DataAccess", "Infrastructure");
-```
-
-### ⚠️ Important Notes
-
-**1. Configuration Not Passed Transitively:**
-
-Configuration is NOT passed to referenced assemblies automatically. Each assembly manages its own conditional services:
-
-```csharp
-// Domain has conditional services → needs configuration
-services.AddDependencyRegistrationsFromDomain(configuration);
-
-// DataAccess also has conditional services → call it directly with configuration
-services.AddDependencyRegistrationsFromDataAccess(configuration);
-
-// Or use transitive registration (but configuration isn't passed through)
-services.AddDependencyRegistrationsFromDomain(configuration, includeReferencedAssemblies: true);
-// ↑ This registers DataAccess services, but they won't have conditional logic applied
-```
-
-**2. Thread-Safe:**
-
-Configuration reading is thread-safe and can be used in concurrent scenarios.
-
-**3. Native AOT Compatible:**
-
-Conditional registration is fully compatible with Native AOT since all checks are simple boolean reads from configuration.
-
-**4. No Circular Dependencies:**
-
-Be careful not to create circular dependencies between conditional services.
-
-### ✅ Benefits
-
-- **🎯 Feature Flags**: Enable/disable features dynamically without redeployment
-- **🌍 Environment-Specific**: Different implementations for dev/staging/prod
-- **🧪 A/B Testing**: Easy experimentation with different implementations
-- **💰 Cost Optimization**: Disable expensive services when not needed
-- **🚀 Gradual Rollout**: Safely test new implementations before full deployment
-- **🎨 Clean Code**: No `#if` preprocessor directives needed
-- **⚡ Runtime Flexibility**: Change service implementations via configuration
-- **🔒 Type-Safe**: All registrations validated at compile time
-
-### 📝 Complete Example
-
-See the **Atc.SourceGenerators.DependencyRegistration** sample for a complete working example:
-
-- **appsettings.json**: Feature flag configuration
-- **RedisCache.cs**: Conditional service (Features:UseRedisCache = true)
-- **MemoryCache.cs**: Conditional service (Features:UseRedisCache = false)
-- **PremiumFeatureService.cs**: Conditional premium features
-- **Program.cs**: Usage demonstration
-
----
-
-## 📚 Additional Examples
-
-See the [sample projects](../sample) for complete working examples:
-
-- **Simple Sample**: [Atc.SourceGenerators.DependencyRegistration](../sample/Atc.SourceGenerators.DependencyRegistration)
-- **Domain Layer**: [Atc.SourceGenerators.DependencyRegistration.Domain](../sample/Atc.SourceGenerators.DependencyRegistration.Domain)
diff --git a/docs/EnumMappingGenerators-Samples.md b/docs/EnumMappingGenerators-Samples.md
deleted file mode 100644
index 2ce58d5..0000000
--- a/docs/EnumMappingGenerators-Samples.md
+++ /dev/null
@@ -1,390 +0,0 @@
-# 🔄 Enum Mapping Sample
-
-This sample demonstrates the **EnumMappingGenerator** in action with realistic enum mapping scenarios including special case handling, bidirectional mappings, and case-insensitive matching.
-
-## 📂 Project Location
-
-```text
-sample/Atc.SourceGenerators.EnumMapping/
-```
-
-## 🚀 Running the Sample
-
-```bash
-cd sample/Atc.SourceGenerators.EnumMapping
-dotnet run
-```
-
-Expected output:
-
-```text
-=== 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! ===
-```
-
-## 🎯 What This Sample Demonstrates
-
-### 1. Special Case Mapping: None → Unknown
-
-**PetStatusEntity.cs**:
-
-```csharp
-[MapTo(typeof(PetStatusDto), Bidirectional = true)]
-public enum PetStatusEntity
-{
- None, // Special case: maps to PetStatusDto.Unknown
- Pending,
- Available,
- Adopted,
-}
-```
-
-**PetStatusDto.cs**:
-
-```csharp
-public enum PetStatusDto
-{
- Unknown, // Special case: maps from PetStatusEntity.None
- Available,
- Pending,
- Adopted,
-}
-```
-
-**Key Points**:
-
-- `None` automatically maps to `Unknown` (common pattern)
-- `Bidirectional = true` generates both forward and reverse mappings
-- All other values map by exact name match
-
-### 2. Exact Name Matching
-
-**FeatureState.cs**:
-
-```csharp
-[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**:
-
-```csharp
-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)
-
-## 📁 Project Structure
-
-```text
-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)
-```
-
-## 🔍 Generated Code
-
-The source generator creates extension methods in the `Atc.Mapping` namespace:
-
-**EnumMappingExtensions.g.cs** (simplified):
-
-```csharp
-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"),
- };
- }
-}
-```
-
-## 🎨 Key Features Demonstrated
-
-### ✅ Special Case Detection
-
-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:**
-
-```csharp
-// 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.
-
-### ✅ Bidirectional Mapping
-
-With `Bidirectional = true`:
-
-```csharp
-[MapTo(typeof(PetStatusDto), Bidirectional = true)]
-public enum PetStatusEntity { ... }
-```
-
-You get **two methods**:
-
-- `PetStatusEntity.MapToPetStatusDto()` (forward)
-- `PetStatusDto.MapToPetStatusEntity()` (reverse)
-
-### ✅ Case-Insensitive Matching
-
-Enum values match regardless of casing:
-
-```csharp
-// These all match:
-SourceEnum.ACTIVE → TargetEnum.Active
-SourceEnum.active → TargetEnum.Active
-SourceEnum.Active → TargetEnum.Active
-SourceEnum.AcTiVe → TargetEnum.Active
-```
-
-### ✅ Compile-Time Safety
-
-Unmapped values generate warnings:
-
-```text
-Warning ATCENUM002: Enum value 'SourceStatus.Deleted' has no matching value in target enum 'TargetStatus'
-```
-
-### ✅ Runtime Safety
-
-Unmapped values throw at runtime:
-
-```csharp
-var status = SourceStatus.Deleted; // Unmapped value
-var dto = status.MapToTargetDto(); // Throws ArgumentOutOfRangeException
-```
-
-## 💡 Usage Patterns
-
-### Pattern 1: Database → Domain → API
-
-**Use Case**: Multi-layer architecture with enum separation
-
-```csharp
-// 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.Unknown
-```
-
-### Pattern 2: Configuration → Domain
-
-**Use Case**: Feature flags with consistent naming
-
-```csharp
-// 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("MyFeature");
-var state = config.MapToFeatureState();
-
-if (state == FeatureState.Active)
-{
- // Feature is active
-}
-```
-
-### Pattern 3: External API → Internal Domain
-
-**Use Case**: Third-party API integration with case normalization
-
-```csharp
-// 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.Unknown
-```
-
-## 🏗️ Real-World Example: PetStore
-
-This pattern is used in the [PetStore sample](PetStoreApi.md) to separate enum concerns across layers:
-
-```text
-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.
-
-## 📝 Notes
-
-- **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
-
-## 📖 Related Samples
-
-- [Object Mapping Sample](ObjectMappingGenerators-Samples.md) - For class-to-class mappings
-- [PetStore Sample](PetStoreApi-Samples.md) - Complete application using all generators
-- [Dependency Registration Sample](DependencyRegistrationGenerators-Samples.md) - DI registration
-- [Options Binding Sample](OptionsBinding-Samples.md) - Configuration binding
-
----
-
-**Need more examples?** Check the [EnumMapping Generator documentation](EnumMappingGenerators.md) for comprehensive guides and patterns.
diff --git a/docs/EnumMappingGenerators.md b/docs/EnumMappingGenerators.md
deleted file mode 100644
index 66ca0c4..0000000
--- a/docs/EnumMappingGenerators.md
+++ /dev/null
@@ -1,745 +0,0 @@
-# 🔄 Enum Mapping Generator
-
-Automatically generate type-safe enum-to-enum mapping code using attributes. The generator creates efficient switch expression mappings at compile time with intelligent name matching and special case handling, eliminating manual enum conversions and reducing errors.
-
-**Key Benefits:**
-
-- 🎯 **Zero runtime cost** - Pure switch expressions generated at compile time
-- 🧠 **Intelligent matching** - Automatic special case detection (None → Unknown, Active → Enabled, etc.)
-- 🔄 **Bidirectional support** - Generate forward and reverse mappings with one attribute
-- 🛡️ **Type-safe** - Compile-time diagnostics for unmapped values
-- ⚡ **Native AOT ready** - No reflection, fully trimming-safe
-
-**Quick Example:**
-
-```csharp
-// Input: Decorate your enum
-[MapTo(typeof(PetStatusDto), Bidirectional = true)]
-public enum PetStatus { None, Available, Adopted }
-
-// Generated: Efficient switch expression
-public static PetStatusDto MapToPetStatusDto(this PetStatus source) =>
- source switch {
- PetStatus.None => PetStatusDto.Unknown, // Special case auto-detected
- PetStatus.Available => PetStatusDto.Available,
- PetStatus.Adopted => PetStatusDto.Adopted,
- _ => throw new ArgumentOutOfRangeException(nameof(source))
- };
-```
-
-## 📖 Documentation Navigation
-
-- **[🎯 Sample Projects](EnumMappingGenerators-Samples.md)** - Working code examples with architecture diagrams
-
-## 📑 Table of Contents
-
-- [� Enum Mapping Generator](#-enum-mapping-generator)
- - [📑 Table of Contents](#-table-of-contents)
- - [🚀 Get Started - Quick Guide](#-get-started---quick-guide)
- - [📂 Project Structure](#-project-structure)
- - [1️⃣ Setup Project](#1️⃣-setup-project)
- - [2️⃣ Define Enums](#2️⃣-define-enums)
- - [3️⃣ Use Generated Mappings](#3️⃣-use-generated-mappings)
- - [🎨 What Gets Generated](#-what-gets-generated)
- - [🎯 Key Takeaways](#-key-takeaways)
- - [✨ Features](#-features)
- - [📦 Installation](#-installation)
- - [💡 Basic Usage](#-basic-usage)
- - [1️⃣ Add Using Directives](#1️⃣-add-using-directives)
- - [2️⃣ Decorate Your Enums](#2️⃣-decorate-your-enums)
- - [3️⃣ Use Generated Mappings](#3️⃣-use-generated-mappings-1)
- - [🏗️ Advanced Scenarios](#️-advanced-scenarios)
- - [🔀 Special Case Mappings](#-special-case-mappings)
- - [🔁 Bidirectional Mapping](#-bidirectional-mapping)
- - [🔤 Case-Insensitive Matching](#-case-insensitive-matching)
- - [🏛️ Multi-Layer Architecture](#️-multi-layer-architecture)
- - [⚙️ MapToAttribute Parameters](#️-maptoattribute-parameters)
- - [🛡️ Diagnostics](#️-diagnostics)
- - [❌ ATCENUM001: Target Type Must Be Enum](#-atcenum001-target-type-must-be-enum)
- - [⚠️ ATCENUM002: Unmapped Enum Value](#️-atcenum002-unmapped-enum-value)
- - [🚀 Native AOT Compatibility](#-native-aot-compatibility)
- - [✅ AOT-Safe Features](#-aot-safe-features)
- - [🏗️ How It Works](#️-how-it-works)
- - [📋 Example Generated Code](#-example-generated-code)
- - [📚 Additional Examples](#-additional-examples)
- - [Example 1: Order Status with None/Unknown](#example-1-order-status-with-noneunknown)
- - [Example 2: Bidirectional Mapping](#example-2-bidirectional-mapping)
- - [Example 3: Case-Insensitive Matching](#example-3-case-insensitive-matching)
- - [🔧 Best Practices](#-best-practices)
- - [📖 Related Documentation](#-related-documentation)
-
----
-
-## 🚀 Get Started - Quick Guide
-
-This guide demonstrates using enum mapping in a realistic application scenario with database entities and API DTOs.
-
-### 📂 Project Structure
-
-```
-PetStore.sln
-├── PetStore.Api/ (Presentation layer - DTOs)
-├── PetStore.Domain/ (Business logic layer - Domain enums)
-└── PetStore.DataAccess/ (Data access layer - Entity enums)
-```
-
-### 1️⃣ Setup Project
-
-**PetStore.DataAccess.csproj**:
-
-```xml
-
-
- net10.0
- enable
-
-
-
-
-
-
-
-```
-
-### 2️⃣ Define Enums
-
-**PetStore.DataAccess/Entities/PetStatusEntity.cs**:
-
-```csharp
-using Atc.SourceGenerators.Annotations;
-
-namespace PetStore.DataAccess.Entities;
-
-///
-/// Pet status in the database layer.
-///
-[MapTo(typeof(Domain.Models.PetStatus), Bidirectional = true)]
-public enum PetStatusEntity
-{
- None, // Will map to PetStatus.Unknown (special case)
- Pending,
- Available,
- Adopted,
-}
-```
-
-**PetStore.Domain/Models/PetStatus.cs**:
-
-```csharp
-namespace PetStore.Domain.Models;
-
-///
-/// Pet status in the domain layer.
-///
-public enum PetStatus
-{
- Unknown, // Maps from PetStatusEntity.None
- Available,
- Pending,
- Adopted,
-}
-```
-
-### 3️⃣ Use Generated Mappings
-
-**PetStore.DataAccess/Repositories/PetRepository.cs**:
-
-```csharp
-using Atc.Mapping; // Generated extension methods live here
-using PetStore.DataAccess.Entities;
-using PetStore.Domain.Models;
-
-public class PetRepository
-{
- public IEnumerable GetByStatus(PetStatus status)
- {
- // Use generated mapping to convert domain enum to entity enum
- var entityStatus = status.MapToPetStatusEntity();
-
- var pets = database
- .Pets
- .Where(p => p.Status == entityStatus)
- .ToList();
-
- // Use generated mapping to convert entities back to domain
- return pets.Select(e => new Pet
- {
- Id = e.Id,
- Name = e.Name,
- Status = e.Status.MapToPetStatus(), // ✨ Generated mapping
- });
- }
-}
-```
-
-### 🎨 What Gets Generated
-
-The generator creates extension methods with switch expressions in the `Atc.Mapping` namespace:
-
-**Generated Code**:
-
-```csharp
-//
-#nullable enable
-
-namespace Atc.Mapping;
-
-///
-/// Extension methods for enum mapping.
-///
-[global::System.CodeDom.Compiler.GeneratedCode("Atc.SourceGenerators.EnumMapping", "1.0.0")]
-public static class EnumMappingExtensions
-{
- ///
- /// Maps
- /// to .
- ///
- public static PetStore.Domain.Models.PetStatus MapToPetStatus(
- this PetStore.DataAccess.Entities.PetStatusEntity source)
- {
- return source switch
- {
- PetStatusEntity.None => PetStatus.Unknown, // Special case mapping
- PetStatusEntity.Pending => PetStatus.Pending,
- PetStatusEntity.Available => PetStatus.Available,
- PetStatusEntity.Adopted => PetStatus.Adopted,
- _ => throw new global::System.ArgumentOutOfRangeException(
- nameof(source), source, "Unmapped enum value"),
- };
- }
-
- ///
- /// Maps
- /// to .
- ///
- public static PetStore.DataAccess.Entities.PetStatusEntity MapToPetStatusEntity(
- this PetStore.Domain.Models.PetStatus source)
- {
- return source switch
- {
- PetStatus.Unknown => PetStatusEntity.None, // Special case mapping
- PetStatus.Available => PetStatusEntity.Available,
- PetStatus.Pending => PetStatusEntity.Pending,
- PetStatus.Adopted => PetStatusEntity.Adopted,
- _ => throw new global::System.ArgumentOutOfRangeException(
- nameof(source), source, "Unmapped enum value"),
- };
- }
-}
-```
-
-### 🎯 Key Takeaways
-
-✅ **Zero Runtime Cost** - Pure switch expressions, no reflection
-✅ **Compile-Time Safety** - Catch errors before runtime
-✅ **Intelligent Matching** - Automatic special case detection (None → Unknown → Default)
-✅ **Case-Insensitive** - Matches enum values regardless of casing
-✅ **Bidirectional** - Generate both forward and reverse mappings with one attribute
-✅ **Runtime Safety** - ArgumentOutOfRangeException for unmapped values
-
----
-
-## ✨ Features
-
-- **🎯 Intelligent Name Matching** - Maps enum values by name with case-insensitive support
-- **🔀 Special Case Detection** - Automatically handles "zero/empty/null" state equivalents:
- - `None` ↔ `Unknown`, `Default`
- - `Unknown` ↔ `None`, `Default`
- - `Default` ↔ `None`, `Unknown`
-- **⚡ Zero Runtime Cost** - Pure switch expressions, no reflection or runtime code generation
-- **🚀 Native AOT Compatible** - Fully trimming-safe, works with Native AOT
-- **🛡️ Type-Safe** - Compile-time validation with diagnostics for unmapped values
-- **🔁 Bidirectional Mapping** - Generate both forward and reverse mappings with `Bidirectional = true`
-- **🔤 Case-Insensitive** - Matches enum values regardless of casing differences
-- **⚠️ Runtime Safety** - `ArgumentOutOfRangeException` thrown for unmapped values
-
----
-
-## 📦 Installation
-
-**Required:**
-
-```bash
-dotnet add package Atc.SourceGenerators
-```
-
-**Optional (recommended for better IntelliSense):**
-
-```bash
-dotnet add package Atc.SourceGenerators.Annotations
-```
-
-Or in your `.csproj`:
-
-```xml
-
-
-
-
-
-
-
-```
-
-**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);CS0436`
-
----
-
-## 💡 Basic Usage
-
-### 1️⃣ Add Using Directives
-
-```csharp
-using Atc.SourceGenerators.Annotations; // For [MapTo]
-using Atc.Mapping; // For generated extension methods
-```
-
-### 2️⃣ Decorate Your Enums
-
-```csharp
-// Source enum
-[MapTo(typeof(StatusDto))]
-public enum StatusEntity
-{
- None,
- Active,
- Inactive,
-}
-
-// Target enum
-public enum StatusDto
-{
- Unknown,
- Active,
- Inactive,
-}
-```
-
-### 3️⃣ Use Generated Mappings
-
-```csharp
-var entity = StatusEntity.None;
-var dto = entity.MapToStatusDto(); // StatusDto.Unknown
-
-Console.WriteLine(dto); // Output: Unknown
-```
-
----
-
-## 🏗️ Advanced Scenarios
-
-### 🔀 Special Case Mappings
-
-The generator automatically handles common enum naming patterns:
-
-```csharp
-// Entity layer
-[MapTo(typeof(StatusDto))]
-public enum StatusEntity
-{
- None, // Maps to StatusDto.Unknown
- Active, // Maps to StatusDto.Active (exact match)
- Inactive, // Maps to StatusDto.Inactive (exact match)
-}
-
-// DTO layer
-public enum StatusDto
-{
- Unknown, // Maps from StatusEntity.None (special case)
- Active, // Maps from StatusEntity.Active (exact match)
- Inactive, // Maps from StatusEntity.Inactive (exact match)
-}
-
-// Usage
-var entity = StatusEntity.None;
-var dto = entity.MapToStatusDto(); // StatusDto.Unknown
-```
-
-**Supported Special Cases**:
-
-- **"Zero/Empty/Null" State Equivalents**: `None` ↔ `Unknown` ↔ `Default`
-- Limited to just these three values to avoid unexpected mappings
-- Use exact name matching for all other enum values
-
-### 🔁 Bidirectional Mapping
-
-Generate both forward and reverse mappings with a single attribute:
-
-```csharp
-[MapTo(typeof(StatusDto), Bidirectional = true)]
-public enum StatusEntity
-{
- None,
- Active,
- Inactive,
-}
-
-// Generated methods:
-// - StatusEntity.MapToStatusDto()
-// - StatusDto.MapToStatusEntity()
-
-var entity = StatusEntity.Active;
-var dto = entity.MapToStatusDto(); // Forward
-var back = dto.MapToStatusEntity(); // Reverse
-```
-
-### 🔤 Case-Insensitive Matching
-
-Enum values match regardless of casing:
-
-```csharp
-[MapTo(typeof(TargetStatus))]
-public enum SourceStatus
-{
- ACTIVE, // Matches TargetStatus.Active
- pending, // Matches TargetStatus.Pending
- InActive, // Matches TargetStatus.Inactive
-}
-
-public enum TargetStatus
-{
- Active,
- Pending,
- Inactive,
-}
-```
-
-### 🏛️ Multi-Layer Architecture
-
-Perfect for 3-layer architectures with clean enum separation:
-
-```
-Database (Entity Enums) → Domain (Model Enums) → API (DTO Enums)
-```
-
-**PetStore.DataAccess/Entities/PetStatusEntity.cs**:
-
-```csharp
-[MapTo(typeof(Domain.Models.PetStatus))]
-public enum PetStatusEntity
-{
- None, // Database: 0 = unknown/null state
- Pending, // Database: 1
- Available, // Database: 2
- Adopted, // Database: 3
-}
-```
-
-**PetStore.Domain/Models/PetStatus.cs**:
-
-```csharp
-[MapTo(typeof(Api.Contract.PetStatus))]
-public enum PetStatus
-{
- Unknown, // Domain: maps from PetStatusEntity.None
- Available, // Domain representation
- Pending,
- Adopted,
-}
-```
-
-**PetStore.Api.Contract/PetStatus.cs**:
-
-```csharp
-public enum PetStatus
-{
- Unknown, // API: client-facing representation
- Available,
- Pending,
- Adopted,
-}
-```
-
-**Complete Mapping Chain**:
-
-```csharp
-// Repository: Entity → Domain
-var entity = database.Pets.First();
-var domain = entity.Status.MapToPetStatus(); // PetStatusEntity → PetStatus
-
-// Service: Domain → DTO
-var dto = domain.MapToPetStatus(); // PetStatus (Domain) → PetStatus (API)
-```
-
----
-
-## ⚙️ MapToAttribute Parameters
-
-| Parameter | Type | Default | Description |
-|----------------|----------|---------|-------------|
-| `targetType` | `Type` | *(required)* | The target enum type to map to. Must be an enum type. |
-| `Bidirectional` | `bool` | `false` | When `true`, generates both forward (Source → Target) and reverse (Target → Source) mappings. |
-
-**Examples**:
-
-```csharp
-// Basic mapping (one direction)
-[MapTo(typeof(StatusDto))]
-public enum StatusEntity { ... }
-
-// Bidirectional mapping (both directions)
-[MapTo(typeof(StatusDto), Bidirectional = true)]
-public enum StatusEntity { ... }
-```
-
----
-
-## 🛡️ Diagnostics
-
-The generator reports diagnostics for potential issues at compile time.
-
-### ❌ ATCENUM001: Target Type Must Be Enum
-
-**Severity**: Error
-**Category**: EnumMapping
-
-**Cause**: The target type specified in `[MapTo(typeof(...))]` is not an enum.
-
-**Example**:
-
-```csharp
-public class StatusDto { } // ❌ Not an enum
-
-[MapTo(typeof(StatusDto))] // ❌ Error ATCENUM001
-public enum StatusEntity
-{
- Active,
- Inactive,
-}
-```
-
-**Fix**: Ensure the target type is an enum.
-
-```csharp
-public enum StatusDto // ✅ Enum type
-{
- Active,
- Inactive,
-}
-
-[MapTo(typeof(StatusDto))] // ✅ OK
-public enum StatusEntity
-{
- Active,
- Inactive,
-}
-```
-
-### ⚠️ ATCENUM002: Unmapped Enum Value
-
-**Severity**: Warning
-**Category**: EnumMapping
-
-**Cause**: A value in the source enum has no matching value in the target enum (including special cases).
-
-**Example**:
-
-```csharp
-public enum TargetStatus
-{
- Active,
- Inactive,
-}
-
-[MapTo(typeof(TargetStatus))]
-public enum SourceStatus
-{
- Active,
- Inactive,
- Deleted, // ⚠️ Warning ATCENUM002: No match for 'Deleted'
- Archived, // ⚠️ Warning ATCENUM002: No match for 'Archived'
-}
-```
-
-**Generated Code** (unmapped values are excluded from switch):
-
-```csharp
-public static TargetStatus MapToTargetStatus(this SourceStatus source)
-{
- return source switch
- {
- SourceStatus.Active => TargetStatus.Active,
- SourceStatus.Inactive => TargetStatus.Inactive,
- // Deleted and Archived are unmapped - will throw at runtime if used
- _ => throw new ArgumentOutOfRangeException(nameof(source), source, "Unmapped enum value"),
- };
-}
-```
-
-**Fix Options**:
-
-1. **Add missing values to target enum**:
-
-```csharp
-public enum TargetStatus
-{
- Active,
- Inactive,
- Deleted, // ✅ Added
- Archived, // ✅ Added
-}
-```
-
-2. **Use exact name matching or rename values**:
-
-```csharp
-public enum TargetStatus
-{
- Active,
- Inactive,
- Deleted, // ✅ Renamed to match source
- Archived, // ✅ Renamed to match source
-}
-```
-
-3. **Accept the warning** if those values should never be used in the mapping context.
-
----
-
-## 🚀 Native AOT Compatibility
-
-The Enum Mapping Generator is **fully compatible with Native AOT** compilation, producing code that meets all AOT requirements:
-
-### ✅ AOT-Safe Features
-
-- **Zero reflection** - All mappings use switch expressions, not reflection-based converters
-- **Compile-time generation** - Mapping code is generated during build, not at runtime
-- **Trimming-safe** - No dynamic type discovery or metadata dependencies
-- **Value type optimization** - Enums remain stack-allocated value types
-- **Static analysis friendly** - All code paths are visible to the AOT compiler
-
-### 🏗️ How It Works
-
-1. **Build-time analysis**: The generator scans enums with `[MapTo]` attributes during compilation
-2. **Switch expression generation**: Creates pure C# switch expressions without any reflection
-3. **Direct value mapping**: Each enum value maps to target value via simple assignment
-4. **AOT compilation**: The generated code compiles to native machine code with full optimizations
-
-### 📋 Example Generated Code
-
-```csharp
-// Source: [MapTo(typeof(Status))] public enum EntityStatus { Active, Inactive }
-
-// Generated AOT-safe code:
-public static Status MapToStatus(this EntityStatus source)
-{
- return source switch
- {
- EntityStatus.Active => Status.Active,
- EntityStatus.Inactive => Status.Inactive,
- _ => throw new global::System.ArgumentOutOfRangeException(
- nameof(source), source, "Unmapped enum value")
- };
-}
-```
-
-**Why This Is AOT-Safe:**
-
-- No `Enum.Parse()` or `Enum.GetValues()` calls (reflection)
-- No dynamic type conversion
-- All branches known at compile time
-- Exception paths are concrete and traceable
-- Zero heap allocations for value type operations
-
----
-
-## 📚 Additional Examples
-
-### Example 1: Order Status with None/Unknown
-
-```csharp
-// Database layer
-[MapTo(typeof(OrderStatusDto))]
-public enum OrderStatusEntity
-{
- None, // → OrderStatusDto.Unknown (special case)
- Pending,
- Completed,
- Cancelled,
-}
-
-// API layer
-public enum OrderStatusDto
-{
- Unknown, // ← OrderStatusEntity.None
- Pending,
- Completed,
- Cancelled,
-}
-
-// Usage
-var entity = OrderStatusEntity.None;
-var dto = entity.MapToOrderStatusDto(); // OrderStatusDto.Unknown
-```
-
-### Example 2: Bidirectional Mapping
-
-```csharp
-// Domain enum
-[MapTo(typeof(StatusDto), Bidirectional = true)]
-public enum StatusEntity
-{
- None, // → StatusDto.Unknown
- Active,
- Inactive,
-}
-
-// DTO enum
-public enum StatusDto
-{
- Unknown, // ← StatusEntity.None
- Active,
- Inactive,
-}
-
-// Usage - both directions work
-var entity = StatusEntity.None;
-var dto = entity.MapToStatusDto(); // StatusDto.Unknown
-var backToEntity = dto.MapToStatusEntity(); // StatusEntity.None (bidirectional)
-```
-
-### Example 3: Case-Insensitive Matching
-
-```csharp
-[MapTo(typeof(TargetPriority))]
-public enum SourcePriority
-{
- LOW, // Matches TargetPriority.Low (case-insensitive)
- MEDIUM, // Matches TargetPriority.Medium
- HIGH, // Matches TargetPriority.High
-}
-
-public enum TargetPriority
-{
- Low,
- Medium,
- High,
-}
-```
-
----
-
-## 🔧 Best Practices
-
-1. **Use Bidirectional When Appropriate**: If you need to convert in both directions, use `Bidirectional = true` to avoid duplicate attributes.
-
-2. **Leverage Special Cases**: The generator knows "zero/empty/null" state equivalents. Use names like `None`/`Unknown`/`Default` to get automatic mappings for these common states.
-
-3. **Handle Warnings**: `ATCENUM002` warnings indicate potential runtime errors. Address them by adding missing values or accepting the risk.
-
-4. **Layer Separation**: Keep enum definitions separate per layer (Entity, Domain, DTO) to maintain clean architecture.
-
-5. **Namespace Organization**: Generated extension methods live in `Atc.Mapping`. Add `using Atc.Mapping;` where you use the mappings.
-
----
-
-## 📖 Related Documentation
-
-- [Object Mapping Generator](ObjectMappingGenerators.md) - For class-to-class mappings
-- [Dependency Registration Generator](DependencyRegistrationGenerators.md) - For automatic DI registration
-- [Options Binding Generator](OptionsBindingGenerators.md) - For configuration binding
-- [Sample Projects](EnumMappingGenerators-Samples.md) - Working code examples
-
----
-
-**Need Help?** Check out the [sample project](EnumMappingGenerators-Samples.md) for a complete working example.
diff --git a/docs/ObjectMappingGenerators-FeatureRoadmap.md b/docs/ObjectMappingGenerators-FeatureRoadmap.md
deleted file mode 100644
index 7c5a3d7..0000000
--- a/docs/ObjectMappingGenerators-FeatureRoadmap.md
+++ /dev/null
@@ -1,1868 +0,0 @@
-# 🗺️ Feature Roadmap - Mapping Generators
-
-This document outlines the feature roadmap for the **EnumMappingGenerator** and **ObjectMappingGenerator**, categorized by priority based on analysis of [Mapperly](https://mapperly.riok.app/docs/intro/) and real-world usage patterns.
-
-## 🔍 Research Sources
-
-This roadmap is based on comprehensive analysis of:
-
-1. **Mapperly Documentation** - [mapperly.riok.app](https://mapperly.riok.app/docs/intro/) - Feature reference
-2. **Mapperly GitHub Repository** - [riok/mapperly](https://github.com/riok/mapperly) - 3.7k⭐, 46 contributors, 1,900+ dependent projects
-3. **Community Feature Requests** - Analysis of 52 open enhancement requests and 66 total issues
-4. **Real-World Usage Patterns** - Based on what users actually request and struggle with
-
-### 📊 Key Insights from Mapperly Community
-
-**Most Requested Features** (by GitHub issue activity):
-
-- **Polymorphic Type Mapping** - Users want better support for derived types and type discriminators
-- **Multi-Source Consolidation** - Merge multiple source objects into one destination
-- **Property Exclusion Shortcuts** - Exclude all properties except explicitly mapped ones
-- **Base Class Configuration** - Inherit mapping configurations from base classes
-- **SnakeCase Naming Strategy** - Map PascalCase to snake_case properties (API scenarios)
-- **IQueryable Projection Improvements** - Better EF Core integration for server-side projections
-
-**Mapperly's Success Factors**:
-
-- ✅ Transparent, readable generated code (developers trust what they can see)
-- ✅ Zero runtime overhead (performance-critical scenarios)
-- ✅ Simple attribute-based API (`[Mapper]` on partial classes)
-- ✅ Comprehensive documentation and examples
-- ✅ Active maintenance and community engagement
-
-## 📊 Current State
-
-### ✅ EnumMappingGenerator - Implemented Features
-
-- **Intelligent name matching** - Case-insensitive enum value matching
-- **Special case detection** - Automatic patterns (None ↔ Unknown, Active ↔ Enabled, etc.)
-- **Bidirectional mapping** - Generate both forward and reverse mappings
-- **Zero runtime cost** - Pure switch expressions, no reflection
-- **Type-safe** - Compile-time diagnostics for unmapped values
-- **Native AOT compatible** - Fully trimming-safe
-
-### ✅ ObjectMappingGenerator - Implemented Features
-
-- **Direct property mapping** - Same name and type properties mapped automatically (case-insensitive)
-- **Constructor mapping** - Automatically detects and uses constructors for records and classes with primary constructors
-- **Mixed initialization** - Constructor parameters + object initializer for remaining properties
-- **Smart enum conversion** - Uses EnumMapping extension methods when available, falls back to casts
-- **Collection mapping** - Automatic mapping of List, IEnumerable, arrays, IReadOnlyList, etc.
-- **Nested object mapping** - Automatic chaining of MapTo methods
-- **Record support** - Works with classes, records, and structs
-- **Null safety** - Proper handling of nullable reference types
-- **Multi-layer support** - Entity → Domain → DTO mapping chains
-- **Bidirectional mapping** - Generate both Source → Target and Target → Source
-- **Extension methods** - Clean, fluent API in `Atc.Mapping` namespace
-- **Native AOT compatible** - Zero reflection, compile-time generation
-
----
-
-## 📋 Feature Status Overview
-
-| Status | Feature | Priority |
-|:------:|---------|----------|
-| ✅ | [Collection Mapping Support](#1-collection-mapping-support) | 🔴 Critical |
-| ✅ | [Constructor Mapping](#2-constructor-mapping) | 🔴 High |
-| ✅ | [Ignore Properties](#3-ignore-properties) | 🔴 High |
-| ✅ | [Custom Property Name Mapping](#4-custom-property-name-mapping) | 🟡 Medium-High |
-| ✅ | [Flattening Support](#5-flattening-support) | 🟡 Medium |
-| ✅ | [Built-in Type Conversion](#6-built-in-type-conversion) | 🟡 Medium |
-| ✅ | [Required Property Validation](#7-required-property-validation) | 🟡 Medium |
-| ✅ | [Polymorphic / Derived Type Mapping](#8-polymorphic--derived-type-mapping) | 🔴 High |
-| ✅ | [Before/After Mapping Hooks](#9-beforeafter-mapping-hooks) | 🟢 Low-Medium |
-| ✅ | [Object Factories](#10-object-factories) | 🟢 Low-Medium |
-| ✅ | [Map to Existing Target Instance](#11-map-to-existing-target-instance) | 🟢 Low-Medium |
-| ✅ | [IQueryable Projections](#13-iqueryable-projections) | 🟢 Low-Medium |
-| ✅ | [Generic Mappers](#14-generic-mappers) | 🟢 Low |
-| ❌ | [Reference Handling / Circular Dependencies](#12-reference-handling--circular-dependencies) | 🟢 Low |
-| ✅ | [Private Member Access](#15-private-member-access) | 🟢 Low |
-| ❌ | [Multi-Source Consolidation](#16-multi-source-consolidation) | 🟢 Low-Medium |
-| ❌ | [Value Converters](#17-value-converters) | 🟢 Low-Medium |
-| ❌ | [Format Providers](#18-format-providers) | 🟢 Low |
-| ✅ | [Property Name Casing Strategies](#19-property-name-casing-strategies-snakecase-camelcase) | 🟢 Low-Medium |
-| ✅ | [Base Class Configuration Inheritance](#20-base-class-configuration-inheritance) | 🟢 Low |
-| 🚫 | [External Mappers / Mapper Composition](#21-external-mappers--mapper-composition) | - |
-| 🚫 | [Advanced Enum Strategies](#22-advanced-enum-strategies-beyond-special-cases) | - |
-| 🚫 | [Deep Cloning Support](#23-deep-cloning-support) | - |
-| 🚫 | [Conditional Mapping](#24-conditional-mapping-map-if-condition-is-true) | - |
-| 🚫 | [Asynchronous Mapping](#25-asynchronous-mapping) | - |
-| 🚫 | [Mapping Configuration Files](#26-mapping-configuration-files-jsonxml) | - |
-| 🚫 | [Runtime Dynamic Mapping](#27-runtime-dynamic-mapping) | - |
-
-**Legend:**
-
-- ✅ **Implemented** - Feature is complete and available
-- ❌ **Not Implemented** - Feature is planned but not yet developed
-- 🚫 **Not Planned** - Feature is out of scope or not aligned with project goals
-
----
-
-## 🎯 Need to Have (High Priority)
-
-These features are essential for real-world usage and align with common mapping scenarios. They should be implemented in the near term.
-
-### 1. Collection Mapping Support
-
-**Priority**: 🔴 **Critical**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.0 - January 2025)
-
-**Description**: Automatically map collections between types (List, IEnumerable, arrays, ICollection, etc.).
-
-**User Story**:
-> "As a developer, I want to map `List` to `List` without manually calling `.Select(u => u.MapToUserDto()).ToList()` every time."
-
-**Example**:
-
-```csharp
-[MapTo(typeof(UserDto))]
-public partial class User
-{
- public Guid Id { get; set; }
- public IList Addresses { get; set; } = new List();
-}
-
-public class UserDto
-{
- public Guid Id { get; set; }
- public IReadOnlyList Addresses { get; set; } = Array.Empty();
-}
-
-// Generated code automatically handles collection mapping:
-Addresses = source.Addresses?.Select(x => x.MapToAddressDto()).ToList()!
-```
-
-**Implementation Details**:
-
-✅ **Supported Collection Types**:
-
-- `List`, `IList` → `.ToList()`
-- `IEnumerable` → `.ToList()`
-- `ICollection`, `IReadOnlyCollection` → `.ToList()`
-- `IReadOnlyList` → `.ToList()`
-- `T[]` (arrays) → `.ToArray()`
-- `Collection` → `new Collection(...)`
-- `ReadOnlyCollection` → `new ReadOnlyCollection(...)`
-
-✅ **Features**:
-
-- Automatic collection type detection
-- LINQ `.Select()` with element mapping method
-- Null-safe handling with `?.` operator
-- Proper collection constructor selection based on target type
-- Works with nested collections and multi-layer architectures
-- Full Native AOT compatibility
-
-✅ **Testing**:
-
-- 5 comprehensive unit tests covering all collection types
-- Tested in PetStore.Api sample across 3 layers:
- - `PetEntity`: `ICollection Children`
- - `Pet`: `IList Children`
- - `PetResponse`: `IReadOnlyList Children`
-
-✅ **Documentation**:
-
-- Added comprehensive section in `docs/generators/ObjectMapping.md`
-- Updated CLAUDE.md with collection mapping details
-- Includes examples and conversion rules
-
----
-
-### 2. Constructor Mapping
-
-**Priority**: 🔴 **High**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.0 - January 2025)
-
-**Description**: Map to types that use constructors instead of object initializers (common with records and immutable types).
-
-**User Story**:
-> "As a developer, I want to map to records and classes with primary constructors without having to manually write constructor calls."
-
-**Example**:
-
-```csharp
-[MapTo(typeof(UserDto))]
-public partial class User
-{
- public Guid Id { get; init; }
- public string Name { get; init; } = string.Empty;
-}
-
-// Target uses constructor
-public record UserDto(Guid Id, string Name);
-
-// Generated code uses constructor:
-return new UserDto(source.Id, source.Name);
-```
-
-**Implementation Details**:
-
-✅ **Constructor Detection**:
-
-- Automatically detects public constructors where ALL parameters match source properties
-- Uses case-insensitive matching (supports `Id` matching `id`, `ID`, etc.)
-- Prefers constructors with more parameters
-- Falls back to object initializer syntax when no matching constructor exists
-
-✅ **Supported Scenarios**:
-
-- **Records with positional parameters** (C# 9+)
-- **Classes with primary constructors** (C# 12+)
-- **Mixed initialization** - Constructor for required parameters + object initializer for remaining properties
-- **Bidirectional mapping** - Both directions automatically detect and use constructors
-
-✅ **Features**:
-
-- Case-insensitive parameter matching (PascalCase properties → camelCase parameters)
-- Automatic ordering of constructor arguments
-- Mixed constructor + initializer generation
-- Works with nested objects and collections
-- Full Native AOT compatibility
-
-✅ **Testing**:
-
-- 9 comprehensive unit tests covering all scenarios:
- - Simple record constructors
- - Record with all properties in constructor
- - Mixed constructor + initializer
- - Bidirectional record mapping
- - Nested object mapping with constructors
- - Enum mapping with constructors
- - Collection mapping with constructors
- - Case-insensitive parameter matching
- - Class-to-record and record-to-record mappings
-
-✅ **Documentation**:
-
-- Added comprehensive section in `docs/generators/ObjectMapping.md`
-- Updated CLAUDE.md with constructor mapping details
-- Includes examples for simple, bidirectional, mixed, and case-insensitive scenarios
-
-✅ **Sample Code**:
-
-- Added `Product` and `Order` examples in `sample/Atc.SourceGenerators.Mapping.Domain`
-- Demonstrates record-to-record and class-to-record mapping with constructors
-
----
-
-### 3. Ignore Properties
-
-**Priority**: 🔴 **High**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.1 - January 2025)
-
-**Description**: Explicitly exclude specific properties from mapping using an attribute.
-
-**User Story**:
-> "As a developer, I want to exclude certain properties (like audit fields or internal state) from being mapped to my DTOs."
-
-**Example**:
-
-```csharp
-using Atc.SourceGenerators.Annotations;
-
-[MapTo(typeof(UserDto))]
-public partial class User
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
-
- [MapIgnore]
- public byte[] PasswordHash { get; set; } = Array.Empty(); // ❌ Never map this
-
- [MapIgnore]
- public DateTime CreatedAt { get; set; } // Internal audit field
-}
-
-public class UserDto
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
- // PasswordHash and CreatedAt are NOT mapped
-}
-```
-
-**Implementation Details**:
-
-✅ **MapIgnoreAttribute Created**:
-
-- Attribute available in Atc.SourceGenerators.Annotations
-- Fallback attribute generated automatically by ObjectMappingGenerator
-- Applied to properties: `[AttributeUsage(AttributeTargets.Property)]`
-
-✅ **Source Property Filtering**:
-
-- Properties with `[MapIgnore]` on source type are excluded from mapping
-- Ignored source properties are never read during mapping generation
-
-✅ **Target Property Filtering**:
-
-- Properties with `[MapIgnore]` on target type are excluded from mapping
-- Ignored target properties are never set during mapping generation
-
-✅ **Features**:
-
-- Works with simple properties
-- Works with nested objects (ignored properties in nested objects are excluded)
-- Works with bidirectional mappings (properties can be ignored in either direction)
-- Works with constructor mappings (ignored properties excluded from constructor parameters)
-- Full Native AOT compatibility
-
-✅ **Testing**:
-
-- 4 comprehensive unit tests covering all scenarios:
- - Source property ignore
- - Target property ignore
- - Nested object property ignore
- - Bidirectional mapping property ignore
-
-✅ **Documentation**:
-
-- Added comprehensive section in `docs/generators/ObjectMapping.md`
-- Updated CLAUDE.md with MapIgnore information
-- Includes examples and use cases
-
-✅ **Sample Code**:
-
-- Added to `User` in `sample/Atc.SourceGenerators.Mapping.Domain`
-- Added to `Pet` in `sample/PetStore.Domain`
-- Demonstrates sensitive data and audit field exclusion
-
----
-
-### 4. Custom Property Name Mapping
-
-**Priority**: 🟡 **Medium-High**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented (v1.1 - January 2025)**
-
-**Description**: Map properties with different names using an attribute to specify the target property name.
-
-**User Story**:
-> "As a developer, I want to map properties with different names (like `FirstName` → `Name`) without having to rename my domain models."
-
-**Example**:
-
-```csharp
-using Atc.SourceGenerators.Annotations;
-
-[MapTo(typeof(UserDto))]
-public partial class User
-{
- public Guid Id { get; set; }
-
- [MapProperty("FullName")]
- public string Name { get; set; } = string.Empty; // Maps to UserDto.FullName
-
- [MapProperty("Age")]
- public int YearsOld { get; set; } // Maps to UserDto.Age
-}
-
-public class UserDto
-{
- public Guid Id { get; set; }
- public string FullName { get; set; } = string.Empty;
- public int Age { get; set; }
-}
-
-// Generated code:
-FullName = source.Name,
-Age = source.YearsOld
-```
-
-**Implementation Details**:
-
-✅ **MapPropertyAttribute Created**:
-
-- Attribute available in Atc.SourceGenerators.Annotations
-- Fallback attribute generated automatically by ObjectMappingGenerator
-- Applied to properties: `[AttributeUsage(AttributeTargets.Property)]`
-- Constructor accepts target property name as string parameter
-
-✅ **Custom Property Name Resolution**:
-
-- Properties with `[MapProperty("TargetName")]` are mapped to the specified target property name
-- Supports both string literals and nameof() expressions
-- Case-insensitive matching for target property names
-
-✅ **Compile-Time Validation**:
-
-- Validates that target property exists on target type at compile time
-- Reports `ATCMAP003` diagnostic if target property is not found
-- Prevents runtime errors by catching mismatches during build
-
-✅ **Features**:
-
-- Works with simple properties (strings, numbers, dates, etc.)
-- Works with nested objects (custom property names on nested object references)
-- Works with bidirectional mappings (apply `[MapProperty]` on both sides)
-- Works with constructor mappings (custom names resolved when matching constructor parameters)
-- Full Native AOT compatibility
-
-✅ **Testing**:
-
-- 4 comprehensive unit tests covering all scenarios:
- - Basic custom property mapping with string literals
- - Bidirectional mapping with custom property names
- - Error diagnostic for non-existent target properties
- - Custom property mapping with nested objects
-
-✅ **Documentation**:
-
-- Added comprehensive section in `docs/generators/ObjectMapping.md`
-- Updated CLAUDE.md with MapProperty information
-- Includes examples and use cases
-- Added `ATCMAP003` diagnostic documentation
-
-✅ **Sample Code**:
-
-- Added to `User` in `sample/Atc.SourceGenerators.Mapping.Domain` (PreferredName → DisplayName)
-- Added to `Pet` in `sample/PetStore.Domain` (NickName → DisplayName)
-- Demonstrates real-world usage patterns
-
----
-
-### 5. Flattening Support
-
-**Priority**: 🟡 **Medium**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.1 - January 2025)
-
-**Description**: Automatically flatten nested properties into a flat structure using naming conventions.
-
-**User Story**:
-> "As a developer, I want to flatten nested objects (like `Address.City`) to flat DTOs (like `AddressCity`) without manual property mapping."
-
-**Example**:
-
-```csharp
-[MapTo(typeof(UserDto), EnableFlattening = true)]
-public partial class User
-{
- public string Name { get; set; } = string.Empty;
- public Address Address { get; set; } = new();
-}
-
-public class Address
-{
- public string City { get; set; } = string.Empty;
- public string Street { get; set; } = string.Empty;
-}
-
-public class UserFlatDto
-{
- public string Name { get; set; } = string.Empty;
- // Flattened properties (convention: {PropertyName}{NestedPropertyName})
- public string AddressCity { get; set; } = string.Empty;
- public string AddressStreet { get; set; } = string.Empty;
-}
-
-// Generated code:
-Name = source.Name,
-AddressCity = source.Address?.City!,
-AddressStreet = source.Address?.Street!
-```
-
-**Implementation Details**:
-
-✅ **Flattening Detection**:
-
-- Opt-in via `EnableFlattening = true` parameter on `[MapTo]` attribute
-- Naming convention: `{PropertyName}{NestedPropertyName}` (e.g., `Address.City` → `AddressCity`)
-- Case-insensitive matching for flattened property names
-- Only flattens class/struct types (not primitive types like string, DateTime)
-
-✅ **Null Safety**:
-
-- Automatically handles nullable nested objects with null-conditional operator (`?.`)
-- Generates `source.Address?.City!` for nullable nested objects
-- Generates `source.Address.City` for non-nullable nested objects
-
-✅ **Features**:
-
-- One-level deep flattening (can be extended to multi-level in future)
-- Works with bidirectional mappings
-- Supports multiple nested objects of the same type (e.g., `HomeAddress`, `WorkAddress`)
-- Compatible with other mapping features (MapIgnore, MapProperty, etc.)
-- Full Native AOT compatibility
-
-✅ **Testing**:
-
-- 4 comprehensive unit tests covering all scenarios:
- - Basic flattening with multiple properties
- - Default behavior (no flattening when disabled)
- - Multiple nested objects of same type
- - Nullable nested objects
-
-✅ **Documentation**:
-
-- Added comprehensive section in `docs/generators/ObjectMapping.md`
-- Updated CLAUDE.md with flattening information
-- Includes examples and use cases
-
-✅ **Sample Code**:
-
-- Added `UserFlatDto` in `sample/Atc.SourceGenerators.Mapping.Contract`
-- Added `PetSummaryResponse` in `sample/PetStore.Api.Contract`
-- Added `Owner` model in `sample/PetStore.Domain`
-- Demonstrates realistic usage with address and owner information
-
----
-
-### 6. Built-in Type Conversion
-
-**Priority**: 🟡 **Medium**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.1 - January 2025)
-
-**Description**: Automatically convert between common types (DateTime ↔ string, int ↔ string, GUID ↔ string, etc.).
-
-**User Story**:
-> "As a developer, I want to convert between common types (like DateTime to string) without writing custom conversion logic."
-
-**Example**:
-
-```csharp
-[MapTo(typeof(UserEventDto))]
-public partial class UserEvent
-{
- public Guid EventId { get; set; }
- public DateTimeOffset Timestamp { get; set; }
- public int DurationSeconds { get; set; }
- public bool Success { get; set; }
-}
-
-public class UserEventDto
-{
- public string EventId { get; set; } = string.Empty; // Guid → string
- public string Timestamp { get; set; } = string.Empty; // DateTimeOffset → string (ISO 8601)
- public string DurationSeconds { get; set; } = string.Empty; // int → string
- public string Success { get; set; } = string.Empty; // bool → string
-}
-
-// Generated code:
-EventId = source.EventId.ToString(),
-Timestamp = source.Timestamp.ToString("O", global::System.Globalization.CultureInfo.InvariantCulture),
-DurationSeconds = source.DurationSeconds.ToString(global::System.Globalization.CultureInfo.InvariantCulture),
-Success = source.Success.ToString()
-```
-
-**Implementation Details**:
-
-✅ **Supported Conversions**:
-
-- `DateTime` ↔ `string` (ISO 8601 format: "O")
-- `DateTimeOffset` ↔ `string` (ISO 8601 format: "O")
-- `Guid` ↔ `string`
-- Numeric types ↔ `string` (int, long, short, byte, decimal, double, float, etc.)
-- `bool` ↔ `string`
-
-✅ **Features**:
-
-- Automatic type detection and conversion code generation
-- Uses InvariantCulture for all numeric and DateTime conversions
-- ISO 8601 format for DateTime/DateTimeOffset to string conversion
-- Parse methods for string to strong type conversions
-- Full Native AOT compatibility
-
-✅ **Testing**:
-
-- 4 comprehensive unit tests covering all scenarios:
- - DateTime/DateTimeOffset/Guid to string conversion
- - String to DateTime/DateTimeOffset/Guid conversion
- - Numeric types to string conversion
- - String to numeric types conversion
-
-✅ **Documentation**:
-
-- Added comprehensive section in `docs/generators/ObjectMapping.md`
-- Includes examples and conversion rules
-
-✅ **Sample Code**:
-
-- Added `UserEvent` and `UserEventDto` in `sample/Atc.SourceGenerators.Mapping`
-- Added `PetDetailsDto` in `sample/PetStore.Api`
-- Demonstrates real-world usage with API endpoints
-
----
-
-### 7. Required Property Validation
-
-**Priority**: 🟡 **Medium**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.1 - January 2025)
-
-**Description**: Validate at compile time that all required properties on the target type are mapped.
-
-**User Story**:
-> "As a developer, I want compile-time errors if I forget to map required properties on my target type."
-
-**Example**:
-
-```csharp
-// ❌ This will generate ATCMAP004 warning at compile time
-[MapTo(typeof(UserRegistrationDto))]
-public partial class UserRegistration
-{
- public Guid Id { get; set; }
- public string FullName { get; set; } = string.Empty;
- // Missing: Email property (required in target)
-}
-
-public class UserRegistrationDto
-{
- public Guid Id { get; set; }
- public required string Email { get; set; } // ⚠️ Required but not mapped
- public required string FullName { get; set; }
-}
-
-// Diagnostic: Warning ATCMAP004: Required property 'Email' on target type 'UserRegistrationDto' has no mapping from source type 'UserRegistration'
-
-// ✅ Correct implementation - all required properties mapped
-[MapTo(typeof(UserRegistrationDto))]
-public partial class UserRegistration
-{
- public Guid Id { get; set; }
- public string Email { get; set; } = string.Empty; // ✅ Required property mapped
- public string FullName { get; set; } = string.Empty; // ✅ Required property mapped
-}
-```
-
-**Implementation Details**:
-
-**Features**:
-
-- Detects `required` keyword on target properties (C# 11+)
-- Generates **ATCMAP004** diagnostic (Warning severity) if required property has no mapping
-- Validates during compilation - catches missing mappings before runtime
-- Warning can be elevated to error via `.editorconfig` or project settings
-- Ignores properties marked with `[MapIgnore]` attribute
-
-**Diagnostic**: `ATCMAP004` - Required property on target type has no mapping
-
-**Severity**: Warning (configurable to Error)
-
-**How It Works**:
-
-1. After property mappings are determined, validator checks all target properties
-2. For each target property marked with `required` keyword:
- - Check if it appears in the property mappings list
- - If not mapped, report ATCMAP004 diagnostic with property name, target type, and source type
-
-**Testing**: 4 unit tests added
-
-- `Generator_Should_Generate_Warning_For_Missing_Required_Property` - Single missing required property
-- `Generator_Should_Not_Generate_Warning_When_All_Required_Properties_Are_Mapped` - All required properties present
-- `Generator_Should_Generate_Warning_For_Multiple_Missing_Required_Properties` - Multiple missing required properties
-- `Generator_Should_Not_Generate_Warning_For_Non_Required_Properties` - Non-required properties can be omitted
-
-**Documentation**: See [Object Mapping - Required Property Validation](ObjectMappingGenerators.md#-required-property-validation)
-
-**Sample Code**:
-
-- `Atc.SourceGenerators.Mapping`: `UserRegistration` → `UserRegistrationDto` (lines in Program.cs)
-- `PetStore.Api`: `Pet` → `UpdatePetRequest` with required Name and Species properties
-
----
-
-### 8. Polymorphic / Derived Type Mapping
-
-**Priority**: 🔴 **High** ⭐ *Highly requested by Mapperly users*
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.0 - January 2025)
-
-**Description**: Support mapping of derived types and interfaces using type checks and pattern matching.
-
-**User Story**:
-> "As a developer, I want to map abstract base classes or interfaces to their concrete implementations based on runtime type."
-
-**Example**:
-
-```csharp
-public abstract class AnimalEntity { }
-public class DogEntity : AnimalEntity { public string Breed { get; set; } = ""; }
-public class CatEntity : AnimalEntity { public int Lives { get; set; } }
-
-public abstract class Animal { }
-public class Dog : Animal { public string Breed { get; set; } = ""; }
-public class Cat : Animal { public int Lives { get; set; } }
-
-[MapTo(typeof(Animal))]
-[MapDerivedType(typeof(Dog), typeof(DogDto))]
-[MapDerivedType(typeof(Cat), typeof(CatDto))]
-public abstract partial class Animal { }
-
-[MapTo(typeof(DogDto))]
-public partial class Dog : Animal { }
-
-[MapTo(typeof(CatDto))]
-public partial class Cat : Animal { }
-
-// Generated code:
-public static AnimalDto MapToAnimalDto(this Animal source)
-{
- if (source is null)
- {
- return default!;
- }
-
- return source switch
- {
- Dog dog => dog.MapToDogDto(),
- Cat cat => cat.MapToCatDto(),
- _ => throw new ArgumentException($"Unknown derived type: {source.GetType().Name}")
- };
-}
-```
-
-**Implementation Details**:
-
-✅ **Implemented Features**:
-
-- `[MapDerivedType(Type sourceType, Type targetType)]` attribute
-- Switch expression generation with type pattern matching
-- Null safety checks for source parameter
-- Automatic delegation to derived type mapping methods
-- Descriptive exception for unmapped derived types
-- Support for multiple derived type mappings via `AllowMultiple = true`
-
-**Testing**: 3 unit tests added
-
-- `Generator_Should_Generate_Polymorphic_Mapping_With_Switch_Expression` - Basic Dog/Cat example
-- `Generator_Should_Handle_Single_Derived_Type_Mapping` - Single derived type
-- `Generator_Should_Support_Multiple_Polymorphic_Mappings` - Three derived types (Circle/Square/Triangle)
-
-**Documentation**: See [Object Mapping - Polymorphic Type Mapping](ObjectMappingGenerators.md#-polymorphic--derived-type-mapping)
-
-**Sample Code**:
-
-- `Atc.SourceGenerators.Mapping`: `Animal` → `AnimalDto` with `Dog`/`Cat` derived types
-- `PetStore.Api`: `Notification` → `NotificationDto` with `EmailNotification`/`SmsNotification` derived types
-
----
-
-## 💡 Nice to Have (Medium Priority)
-
-These features would improve usability and flexibility but are not critical for initial adoption. They can be implemented based on user feedback and demand.
-
-### 9. Before/After Mapping Hooks
-
-**Priority**: 🟢 **Low-Medium**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.1 - January 2025)
-
-**Description**: Execute custom logic before or after the mapping operation.
-
-**User Story**:
-> "As a developer, I want to execute custom validation or post-processing logic before or after mapping objects, without having to write wrapper methods around the generated mapping code."
-
-**Example**:
-
-```csharp
-using Atc.SourceGenerators.Annotations;
-
-[MapTo(typeof(UserDto), BeforeMap = nameof(ValidateUser), AfterMap = nameof(EnrichDto))]
-public partial class User
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
-
- // Called before the mapping operation (after null check)
- private static void ValidateUser(User source)
- {
- if (string.IsNullOrWhiteSpace(source.Name))
- {
- throw new ArgumentException("Name cannot be empty");
- }
- }
-
- // Called after the mapping operation (before return)
- private static void EnrichDto(User source, UserDto target)
- {
- target.DisplayName = $"{source.Name} (ID: {source.Id})";
- }
-}
-
-public class UserDto
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
- public string DisplayName { get; set; } = string.Empty;
-}
-
-// Generated code:
-public static UserDto MapToUserDto(this User source)
-{
- if (source is null)
- {
- return default!;
- }
-
- // BeforeMap hook - called after null check, before mapping
- User.ValidateUser(source);
-
- var target = new UserDto
- {
- Id = source.Id,
- Name = source.Name
- };
-
- // AfterMap hook - called after mapping, before return
- User.EnrichDto(source, target);
-
- return target;
-}
-```
-
-**Implementation Details**:
-
-✅ **BeforeMap Hook**:
-
-- Called after null check, before object creation
-- Signature: `static void MethodName(SourceType source)`
-- Use for validation, preprocessing, or throwing exceptions
-- Has access to source object only
-
-✅ **AfterMap Hook**:
-
-- Called after object creation, before return
-- Signature: `static void MethodName(SourceType source, TargetType target)`
-- Use for post-processing, enrichment, or additional property setting
-- Has access to both source and target objects
-
-✅ **Features**:
-
-- Hook methods must be static
-- Hooks are called via fully qualified name (e.g., `User.ValidateUser(source)`)
-- Both hooks are optional - use one, both, or neither
-- Hooks are specified by method name as string (e.g., `BeforeMap = nameof(ValidateUser)`)
-- Works with all mapping features (collections, nested objects, constructors, etc.)
-- Reverse mappings (Bidirectional = true) do not inherit hooks
-- Full Native AOT compatibility
-
-✅ **Execution Order**:
-
-1. Null check on source
-2. **BeforeMap hook** (if specified)
-3. Polymorphic type check (if derived type mappings exist)
-4. Object creation (constructor or object initializer)
-5. **AfterMap hook** (if specified)
-6. Return target object
-
-✅ **Testing**:
-
-- 3 comprehensive unit tests covering all scenarios:
- - BeforeMap hook called before mapping
- - AfterMap hook called after mapping
- - Both hooks called in correct order
-
-✅ **Documentation**:
-
-- Added comprehensive section in `docs/generators/ObjectMapping.md`
-- Updated CLAUDE.md with hooks information
-- Includes examples and use cases
-
-✅ **Sample Code**:
-
-- Planned to be added to `sample/Atc.SourceGenerators.Mapping`
-- Planned to be added to `sample/PetStore.Api`
-
-**Use Cases**:
-
-- **Validation** - Throw exceptions if source data is invalid before mapping
-- **Logging** - Log mapping operations for debugging
-- **Enrichment** - Add computed properties to target that don't exist in source
-- **Auditing** - Track when objects are mapped
-- **Side Effects** - Call external services or update caches
-
----
-
-### 10. Object Factories
-
-**Priority**: 🟢 **Low-Medium**
-**Generator**: ObjectMappingGenerator
-**Status**: ✅ **Implemented** (v1.1 - January 2025)
-
-**Description**: Use custom factory methods for object creation instead of `new()`.
-
-**User Story**:
-> "As a developer, I want to use custom factory methods to create target instances during mapping, so I can initialize objects with default values, use object pooling, or apply other custom creation logic."
-
-**Example**:
-
-```csharp
-using Atc.SourceGenerators.Annotations;
-
-[MapTo(typeof(UserDto), Factory = nameof(CreateUserDto))]
-public partial class User
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
-
- // Factory method creates the target instance
- internal static UserDto CreateUserDto()
- {
- return new UserDto
- {
- CreatedAt = DateTimeOffset.UtcNow, // Set default value
- };
- }
-}
-
-public class UserDto
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
- public DateTimeOffset CreatedAt { get; set; }
-}
-
-// Generated code:
-public static UserDto MapToUserDto(this User source)
-{
- if (source is null)
- {
- return default!;
- }
-
- var target = User.CreateUserDto(); // Factory creates instance
-
- target.Id = source.Id; // Property mappings applied
- target.Name = source.Name;
-
- return target;
-}
-```
-
-**Implementation Details**:
-
-✅ **Factory Method**:
-
-- Signature: `static TargetType MethodName()`
-- Replaces `new TargetType()` for object creation
-- Property mappings are applied after factory creates the instance
-- Factory method must be static and accessible
-
-✅ **Features**:
-
-- Factory method specified by name (e.g., `Factory = nameof(CreateUserDto)`)
-- Fully compatible with BeforeMap/AfterMap hooks
-- Works with all mapping features (nested objects, collections, etc.)
-- Reverse mappings (Bidirectional = true) do not inherit factory methods
-- Full Native AOT compatibility
-
-✅ **Execution Order**:
-
-1. Null check on source
-2. **BeforeMap hook** (if specified)
-3. **Factory method** creates target instance
-4. Property mappings applied to target
-5. **AfterMap hook** (if specified)
-6. Return target object
-
-✅ **Testing**:
-
-- 3 unit tests added (skipped in test harness, manually verified in samples)
-- Tested with BeforeMap/AfterMap hooks
-- Verified property mapping after factory creation
-
-✅ **Documentation**:
-
-- Added comprehensive section in `docs/generators/ObjectMapping.md`
-- Updated CLAUDE.md with factory information
-- Includes examples and use cases
-
-✅ **Sample Code**:
-
-- Added to `sample/PetStore.Api` (EmailNotification with factory)
-- Demonstrates factory method with runtime default values
-
-**Use Cases**:
-
-- **Default Values** - Set properties that don't exist in source (e.g., CreatedAt timestamp)
-- **Object Pooling** - Reuse objects from a pool for performance
-- **Lazy Initialization** - Defer expensive initialization until needed
-- **Dependency Injection** - Use service locator pattern to create instances
-- **Custom Logic** - Apply any custom creation logic (caching, logging, etc.)
-
-**Limitations**:
-
-- Factory pattern doesn't work with init-only properties (records with `init` setters)
-- For init-only properties, use constructor mapping or object initializers instead
-
----
-
-### 11. Map to Existing Target Instance
-
-**Priority**: 🟢 **Low-Medium**
-**Status**: ✅ **Implemented**
-
-**Description**: Update an existing object instead of creating a new one (useful for EF Core tracked entities).
-
-**User Story**:
-> "As a developer working with EF Core, I want to update existing tracked entities without creating new instances, so that EF Core's change tracking works correctly and I can efficiently update database records."
-
-**Implementation Details**:
-
-When `UpdateTarget = true` is specified in the `MapToAttribute`, the generator creates **two methods**:
-
-1. **Standard method** - Creates and returns a new instance:
-
- ```csharp
- public static TargetType MapToTargetType(this SourceType source)
- ```
-
-2. **Update method** - Updates an existing instance (void return):
-
- ```csharp
- public static void MapToTargetType(this SourceType source, TargetType target)
- ```
-
-**Generated Code Pattern**:
-
-```csharp
-// Input:
-[MapTo(typeof(UserDto), UpdateTarget = true)]
-public partial class User
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
- public string Email { get; set; } = string.Empty;
-}
-
-// Generated output (both methods):
-public static UserDto MapToUserDto(this User source)
-{
- if (source is null) return default!;
-
- return new UserDto
- {
- Id = source.Id,
- Name = source.Name,
- Email = source.Email
- };
-}
-
-public static void MapToUserDto(this User source, UserDto target)
-{
- if (source is null) return;
- if (target is null) return;
-
- target.Id = source.Id;
- target.Name = source.Name;
- target.Email = source.Email;
-}
-```
-
-**Testing Status**:
-
-- ✅ Unit tests added (`Generator_Should_Generate_Update_Target_Method`)
-- ✅ Unit tests added (`Generator_Should_Not_Generate_Update_Target_Method_When_False`)
-- ✅ Unit tests added (`Generator_Should_Include_Hooks_In_Update_Target_Method`)
-- ✅ All tests passing (171 succeeded, 13 skipped)
-
-**Sample Code Locations**:
-
-- `sample/Atc.SourceGenerators.Mapping.Domain/Settings.cs` - Simple update target example
-- `sample/PetStore.Domain/Models/Pet.cs` - EF Core entity update example (with `Bidirectional = true`)
-
-**Use Cases**:
-
-1. **EF Core Tracked Entities**:
-
- ```csharp
- // Fetch tracked entity from database
- var existingPet = await dbContext.Pets.FindAsync(petId);
-
- // Update it with new data (EF Core tracks changes)
- domainPet.MapToPetEntity(existingPet);
-
- // Save changes (only modified properties are updated in database)
- await dbContext.SaveChangesAsync();
- ```
-
-2. **Reduce Object Allocations**:
-
- ```csharp
- // Reuse existing DTO instance
- var settingsDto = new SettingsDto();
-
- settings1.MapToSettingsDto(settingsDto);
- // ... use settingsDto
-
- settings2.MapToSettingsDto(settingsDto); // Reuse same instance
- // ... use settingsDto
- ```
-
-3. **Update UI ViewModels**:
-
- ```csharp
- // Update existing ViewModel without creating new instance
- var viewModel = this.DataContext as UserViewModel;
- updatedUser.MapToUserViewModel(viewModel);
- ```
-
-**Important Notes**:
-
-- The update method performs **null checks** for both source and target
-- The update method has a **void return type** (no return value)
-- **BeforeMap** and **AfterMap** hooks are fully supported in both methods
-- The update method **does not use Factory** (factory is only for creating new instances)
-- Works seamlessly with **Bidirectional = true** (both directions get update overloads)
-- All properties are updated, including nullable properties
-
-**When to Use**:
-
-- ✅ Updating EF Core tracked entities
-- ✅ Reducing allocations for frequently mapped objects
-- ✅ Updating existing ViewModels or DTOs
-- ✅ Scenarios where you need to preserve object identity
-
-**When NOT to Use**:
-
-- ❌ When you always need new instances
-- ❌ With immutable types (records with init-only properties)
-- ❌ When Factory method is needed (factory creates new instances)
-
----
-
-### 12. Reference Handling / Circular Dependencies
-
-**Priority**: 🟢 **Low**
-**Status**: ❌ Not Implemented
-
-**Description**: Handle circular references and maintain object identity during mapping.
-
-**Example**:
-
-```csharp
-public class User
-{
- public List Posts { get; set; } = new();
-}
-
-public class Post
-{
- public User Author { get; set; } = null!; // Circular reference
-}
-
-// Need to track mapped instances to avoid infinite recursion
-```
-
----
-
-### 13. IQueryable Projections
-
-**Priority**: 🟢 **Low-Medium**
-**Status**: ✅ **Implemented** (v1.2 - January 2025)
-
-**Description**: Generate `Expression>` for use in EF Core `.Select()` queries (server-side projection).
-
-**User Story**:
-> "As a developer using EF Core, I want to project database queries to DTOs server-side without fetching unnecessary data, so that I can improve query performance and reduce database load."
-
-**Example**:
-
-```csharp
-[MapTo(typeof(UserSummaryDto), GenerateProjection = true)]
-public partial class User
-{
- public Guid Id { get; set; }
- public string FirstName { get; set; } = string.Empty;
- public string LastName { get; set; } = string.Empty;
- public string Email { get; set; } = string.Empty;
- public UserStatusDto Status { get; set; }
- public DateTimeOffset CreatedAt { get; set; }
-}
-
-// Generated expression:
-public static Expression> ProjectToUserSummaryDto()
-{
- return source => new UserSummaryDto
- {
- Id = source.Id,
- FirstName = source.FirstName,
- LastName = source.LastName,
- Email = source.Email,
- Status = (UserStatusDto)source.Status,
- CreatedAt = source.CreatedAt
- };
-}
-
-// Usage with EF Core:
-var users = await dbContext.Users
- .Where(u => u.IsActive)
- .Select(User.ProjectToUserSummaryDto())
- .ToListAsync();
-// SQL: SELECT Id, FirstName, LastName, Email, Status, CreatedAt FROM Users WHERE IsActive = 1
-```
-
-**Implementation Details**:
-
-✅ **GenerateProjection Property**:
-
-- Opt-in via `GenerateProjection = true` parameter on `[MapTo]` attribute
-- Generates a static method that returns `Expression