Chd.Mapping.Roslyn.Advanced 8.0.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package Chd.Mapping.Roslyn.Advanced --version 8.0.3
                    
NuGet\Install-Package Chd.Mapping.Roslyn.Advanced -Version 8.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Chd.Mapping.Roslyn.Advanced" Version="8.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Chd.Mapping.Roslyn.Advanced" Version="8.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Chd.Mapping.Roslyn.Advanced" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Chd.Mapping.Roslyn.Advanced --version 8.0.3
                    
#r "nuget: Chd.Mapping.Roslyn.Advanced, 8.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Chd.Mapping.Roslyn.Advanced@8.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Chd.Mapping.Roslyn.Advanced&version=8.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Chd.Mapping.Roslyn.Advanced&version=8.0.3
                    
Install as a Cake Tool

Chd.Mapping.Roslyn.Advanced – High-Performance, Expression-Aware Source Generator for .NET Mapping

NuGet License

📝 Table of Contents


🧐 About

Chd.Mapping.Roslyn.Advanced is a modern, compile-time object mapper for .NET, built with Roslyn source generators. It automatically creates fast, type-safe, and debuggable mapping code between DTOs and entities during your build process—eliminating runtime reflection, configuration headaches, and mapping errors typical of tools like AutoMapper or Mapster.

This advanced version supports not only property-to-property mapping, but also expression-based mapping for calculated or derived properties, nested object mapping, and high-performance scenarios.


🚀 Why Chd.Mapping.Roslyn.Advanced?

  • Zero Reflection, Maximum Speed: All mapping logic is generated at build time. No runtime cost, no dynamic code, no hidden performance penalty.
  • Type Safety: All mapping is verified at build—if your DTO or entity changes, mapping errors become compiler errors, not runtime bugs.
  • Debuggability: All generated mapping code is standard C#, fully visible in your IDE. Set breakpoints, watch variables, and step through mappings with the debugger.
  • Simplicity: No configuration files, no dependency injection, no startup scanning, no magic. Just add attributes, build, and use.
  • Advanced Scenarios: Supports custom expressions, nested objects, collections, and property name mismatches with a single attribute.

✨ Features

  • Attribute-based mapping: [MapTo], [MapProperty] (with expression support)
  • Compile-time generation of implicit mapping operators
  • Expression-based property mapping (e.g., NetTotal = Price + Tax - Discount)
  • Nested and collection mapping support
  • No runtime dependency, no reflection, no configuration files
  • Full support for .NET 8+, .NET 9, and .NET Standard 2.0 SDK-style projects

📦 Installation

Install via .NET CLI:

dotnet add package Chd.Mapping.Roslyn.Advanced

Or via NuGet Package Manager Console:

Install-Package Chd.Mapping.Roslyn.Advanced

Compatible with all SDK-style projects – .NET Core 3.1+, .NET 5+, .NET 6+, .NET 7+.


🎈 Usage

1. Basic Mapping

Scenario: Map between DTO and Entity with matching property names—no configuration needed.

using Chd.Mapping.Abstractions;
using System;

[MapTo(typeof(UserEntity))]
public class UserDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public partial class UserEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Program
{
    static void Main()
    {
        var dto = new UserDto { Id = 1, Name = "Alice" };
        UserEntity entity = dto;  // Implicit mapping

        Console.WriteLine($"Id: {entity.Id}");
        Console.WriteLine($"Name: {entity.Name}");
    }
}

Console Output:

Id: 1
Name: Alice

2. Advanced Property Mapping

Scenario: Map between differently named properties, or apply custom logic and expressions.

using Chd.Mapping.Abstractions;
using System;

[MapTo(typeof(UserEntity))]
public class UserDto
{
    public int Id { get; set; }
    [MapProperty("FullName")] // Maps DTO.Name → Entity.FullName
    public string Name { get; set; }
}

public partial class UserEntity
{
    public int Id { get; set; }
    public string FullName { get; set; }
}

class Program
{
    static void Main()
    {
        var dto = new UserDto { Id = 42, Name = "Mehmet Yoldaş" };
        UserEntity entity = dto;  // Mapping with different property name

        Console.WriteLine($"Id: {entity.Id}");
        Console.WriteLine($"FullName: {entity.FullName}");
    }
}

Console Output:

Id: 42
FullName: Mehmet Yoldaş

Expression-Based Mapping
using Chd.Mapping.Abstractions;
using System;

[MapTo(typeof(OrderEntity))]
public class OrderDto
{
    public decimal Price { get; set; }
    public decimal Tax { get; set; }
    public decimal Discount { get; set; }

    [MapProperty("Price + Tax - Discount")]
    public decimal NetTotal { get; set; }

    public string Name { get; set; }
    public string Surname { get; set; }

    [MapProperty("Name + ' ' + Surname")]
    public string FullName { get; set; }

    public bool IsActive { get; set; }
    
    [MapProperty("IsActive ? 'Active' : 'Passive'")]
    public string StatusText { get; set; }
}

public partial class OrderEntity
{
    public decimal Price { get; set; }
    public decimal Tax { get; set; }
    public decimal Discount { get; set; }
    public decimal NetTotal { get; set; }
    public string FullName { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public string StatusText { get; set; }
    public bool IsActive { get; set; }
}

class Program
{
    static void Main()
    {
        var dto = new OrderDto
        {
            Price = 200,
            Tax = 36,
            Discount = 16,
            Name = "Ayşe",
            Surname = "Kaya",
            IsActive = false
        };

        OrderEntity entity = dto;

        Console.WriteLine($"NetTotal: {entity.NetTotal}");           // 220
        Console.WriteLine($"FullName: {entity.FullName}");           // Ayşe Kaya
        Console.WriteLine($"StatusText: {entity.StatusText}");       // Passive
    }
}

Console Output:

NetTotal: 220
FullName: Ayşe Kaya
StatusText: Passive

Tip:
You can use either single quotes (' ') or double quotes (" ") for string concatenation in expressions.
For readability, the recommended style is single quotes (' '), as in [MapProperty("Name + ' ' + Surname")].


3. Nested and Collection Mapping

Scenario: Map nested objects and collections automatically.

using Chd.Mapping.Abstractions;
using System;
using System.Collections.Generic;

[MapTo(typeof(ProductEntity))]
public class ProductDto
{
    public string Code { get; set; }
    public int Quantity { get; set; }
}

public partial class ProductEntity
{
    public string Code { get; set; }
    public int Quantity { get; set; }
}

[MapTo(typeof(OrderEntity))]
public class OrderDto
{
    public int OrderId { get; set; }
    public List<ProductDto> Products { get; set; }
}

public partial class OrderEntity
{
    public int OrderId { get; set; }
    public List<ProductEntity> Products { get; set; }
}

class Program
{
    static void Main()
    {
        var dto = new OrderDto
        {
            OrderId = 3,
            Products = new List<ProductDto>
            {
                new ProductDto { Code = "A123", Quantity = 2 },
                new ProductDto { Code = "B456", Quantity = 5 }
            }
        };

        OrderEntity entity = dto;

        Console.WriteLine($"OrderId: {entity.OrderId}");
        foreach (var p in entity.Products)
            Console.WriteLine($"Product: {p.Code} - {p.Quantity}");
    }
}

Console Output:

OrderId: 3
Product: A123 - 2
Product: B456 - 5

4. Debugging and Maintainability

  • All generated mapping code is standard C#, located in /obj or /Generated folders.
  • You can set breakpoints, watch variables, and step through mappings with the debugger.
  • Example generated code:
    public static implicit operator UserEntity(UserDto dto)
    {
        if (dto == null) return null;
        return new UserEntity
        {
            Id = dto.Id,
            Name = dto.Name,
            // ... other properties
        };
    }
    

🚦 Performance

Scenario AutoMapper (ms) Mapster (ms) Chd.Mapping.Roslyn.Advanced (ms)
1,000,000 DTO→Entity mappings 980 410 180
100,000 Entity→DTO mappings w/nesting 180 74 34
Flat object, assign all properties 22 10 4

Source: Internal benchmarks, see /benchmarks.

Key Takeaway:
Chd.Mapping.Roslyn.Advanced mapping is as fast as hand-written code, and dramatically faster than reflection-based mappers.


🏆 Best Practices & Tips

  • Mark all mapped classes as partial.
  • Use [MapTo(typeof(TargetType))] on your DTOs.
  • Use [MapProperty("...")] for calculated or custom-mapped properties.
  • Run a build to regenerate mapping code after model changes.
  • No Fody, no config files, no runtime setup required.

⚠️ Limitations

  • [MapProperty] attribute only supports a single string parameter: use either the target property name or a full C# expression.
  • Expressions must be valid C# and use property names exactly as declared.
  • Nested mapping works if types on both sides also have [MapTo] or compatible structure.
  • Custom type conversions outside of C# syntax, external services, complex global mapping config are not supported.
  • Circular object graph mapping is not supported.
  • Classes marked with [MapTo] must be declared as partial.
    • If you forget to add partial, you’ll see a build-time diagnostic error (MAP001):
      "Class 'X' is marked with [MapTo] and must be declared as partial"
    • Visual Studio, Rider, and similar IDEs provide a quick fix (lightbulb action) for this — “Add 'partial' modifier”.
    • With a single click, the partial keyword is automatically added to your class declaration:
      // Incorrect:
      [MapTo(typeof(Entity))]
      public class MyDto { ... }
      
      // Fixed:
      [MapTo(typeof(Entity))]
      public partial class MyDto { ... }
      

🚑 Troubleshooting

  • MAP001: Class must be partial
    • Solution: Add partial to your class declaration (e.g., public partial class ...).
    • Your IDE (VS, Rider) typically offers a quick fix ("Add 'partial' modifier"/lightbulb) for this – just click to apply the fix!
  • Build error after changing models: Run a clean build (dotnet clean && dotnet build). Check generated sources in /obj.
  • Attribute typo or syntax error: Ensure [MapTo] and [MapProperty] are spelled correctly, and property names are valid.
  • Expression compile errors: Expressions must be valid C#. If an error occurs, check the generated code and fix the expression.

🕵️‍♂️ Viewing the Generated Mapping Code

  • Open /obj/Debug/net*/*Mapping*.g.cs (or your IDE’s generated files node) to inspect all mapping operator code.
  • You can debug into the generated code just like any hand-written C#.

❓ FAQ

Q: Do I need to write any mapping code?
A: No. Just add attributes and build – all mapping code is generated for you.

Q: Can I debug the generated code?
A: Yes! All generated code is standard C# and fully debuggable.

Q: Is there any runtime dependency?
A: No. All mapping logic is generated at compile time.

Q: What if I change my DTO or Entity?
A: The generator will update mappings on the next build. Mapping errors become compiler errors.


🤝 Contributing

Contributions, issues and feature requests are welcome!
Check issues page or submit a pull request.

✍️ Authors

🎉 Acknowledgments

  • Thanks to all contributors and users of the CHD library ecosystem.
  • Inspired by best practices in .NET library design.

For issues, feature requests, or contributions, please visit the GitHub repository

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.1.3 126 2/28/2026
8.1.2 110 2/19/2026
8.1.1 278 1/28/2026
8.0.9 119 1/23/2026
8.0.7 126 1/21/2026
8.0.6 117 1/20/2026
8.0.5 111 1/20/2026
8.0.4 114 1/20/2026
8.0.3 116 1/20/2026
8.0.2 117 1/20/2026
8.0.1 116 1/19/2026