Chd.Mapping.Roslyn.Advanced 8.1.3

dotnet add package Chd.Mapping.Roslyn.Advanced --version 8.1.3
                    
NuGet\Install-Package Chd.Mapping.Roslyn.Advanced -Version 8.1.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.1.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.1.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.1.3
                    
#r "nuget: Chd.Mapping.Roslyn.Advanced, 8.1.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.1.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.1.3
                    
Install as a Cake Addin
#tool nuget:?package=Chd.Mapping.Roslyn.Advanced&version=8.1.3
                    
Install as a Cake Tool

📘 Chd.Mapping.Roslyn.Advanced – High-Performance, Expression-Aware DTO Mapper

NuGet License Downloads

Chd (Cleverly Handle Difficulty) library helps you cleverly handle difficulty, write code quickly, and keep your application stable.

Chd.Mapping.Roslyn.Advanced is a blazing-fast, compile-time object mapper for .NET with expression-based mapping support—built on Roslyn source generators for maximum performance and type safety!


📑 Table of Contents

  1. About
  2. Why This Package?
  3. Features
  4. Installation
  5. Quick Start
  6. Usage Examples
  7. Performance
  8. Best Practices
  9. Limitations
  10. Troubleshooting
  11. Viewing Generated Code
  12. FAQ
  13. Examples Repository
  14. Contributing
  15. Authors
  16. Acknowledgments

🧐 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 this package

  • 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., [MapProperty(Price + Tax - Discount))
  • No runtime logic. Just generated code: (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

Or via Package Manager UI in Visual Studio / Rider.

Requirements:

  • .NET Standard 2.0+
  • .NET Core 3.1+
  • .NET 5, 6, 7, 8, 9+
  • C# 8.0 or higher

🚀 Quick Start

using Chd.Mapping.Abstractions;

// 1. Mark your DTO with [MapTo] and expression mapping
[MapTo(typeof(OrderEntity))]
public partial class OrderDto
{
    public decimal Price { get; set; }
    public decimal Tax { get; set; }
    public decimal Discount { get; set; }

    // Expression-based calculated property!
    [MapProperty("Price * (Tax + 100) / 100 - Discount")]
    public decimal NetTotal { get; set; }
}

// 2. Define your Entity (must be partial)
public partial class OrderEntity
{
    public decimal Price { get; set; }
    public decimal Tax { get; set; }
    public decimal Discount { get; set; }
    public decimal NetTotal { get; set; }
}

// 3. Use implicit operators - that's it!
var dto = new OrderDto { Price = 100, Tax = 18, Discount = 2 };
OrderEntity entity = dto;  // DTO → Entity with calculation!

Console.WriteLine($"NetTotal: {entity.NetTotal}");  // Output: 116

Output:

NetTotal: 116

✅ Expression-based mapping! ✅ No reflection overhead! ✅ Full IntelliSense support! ✅ Compile-time validation!


💡 Usage Examples

1. Basic Mapping

Scenario: Simple DTO ↔ Entity mapping with identical property names.

using Chd.Mapping.Abstractions;
using System;

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

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

class Program
{
    static void Main()
    {
        // DTO to Entity
        var dto = new UserDto 
        { 
            Id = 1, 
            Name = "Mehmet",
            Email = "mehmet@example.com"
        };

        UserEntity entity = dto;  // Implicit mapping
        Console.WriteLine($"Entity: {entity.Id}, {entity.Name}, {entity.Email}");

        // Entity back to DTO
        UserDto dto2 = entity;
        Console.WriteLine($"DTO: {dto2.Id}, {dto2.Name}, {dto2.Email}");
    }
}

Console Output:

Entity: 1, Mehmet, mehmet@example.com
DTO: 1, Mehmet, mehmet@example.com

2. Advanced Property Mapping

Scenario: Map properties with different names.

using Chd.Mapping.Abstractions;
using System;

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

    [MapProperty("FullName")]  // Maps DTO.Name → Entity.FullName
    public string Name { get; set; }

    [MapProperty("EmailAddress")]  // Maps DTO.Email → Entity.EmailAddress
    public string Email { get; set; }
}

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

class Program
{
    static void Main()
    {
        var dto = new UserDto 
        { 
            Id = 42, 
            Name = "Mehmet Yoldaş",
            Email = "mehmet@example.com"
        };

        UserEntity entity = dto;

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

Console Output:

Id: 42
FullName: Mehmet Yoldaş
EmailAddress: mehmet@example.com

Expression-Based Mapping

🔥 The Power of Advanced Mapping: Calculate derived properties with C# expressions!

using Chd.Mapping.Abstractions;
using System;

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

    // Mathematical expression
    [MapProperty("Price * (Tax + 100) / 100 - Discount")]
    public decimal NetTotal { get; set; }

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

    // String concatenation with single quotes
    [MapProperty("Name + ' ' + Surname")]
    public string FullName { get; set; }

    public bool IsActive { get; set; }

    // Ternary operator
    [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 Name { get; set; }
    public string Surname { get; set; }
    public string FullName { get; set; }
    public bool IsActive { get; set; }
    public string StatusText { get; set; }
}

class Program
{
   static void Main()
   {
      var dto = new OrderDto 
      { 
          Price = 100, 
          Tax = 18, 
          Discount = 2, 
          Name = "Mehmet", 
          Surname = "Yoldaş", 
          IsActive = true 
      };

      OrderEntity entity = dto;  // Expression-based mapping!

      Console.WriteLine($"NetTotal: {entity.NetTotal}");           // 116
      Console.WriteLine($"FullName: {entity.FullName}");           // Mehmet Yoldaş
      Console.WriteLine($"StatusText: {entity.StatusText}");       // Active

      // Reverse mapping works too!
      OrderDto dto2 = entity;
      Console.WriteLine($"DTO NetTotal: {dto2.NetTotal}");         // 116
   }
}

Console Output:

NetTotal: 116
FullName: Mehmet Yoldaş
StatusText: Active
DTO NetTotal: 116

💡 Pro Tip:
You can use either single quotes (' ') or double quotes (" ") for string literals in expressions.
Recommended style: Single quotes ([MapProperty("Name + ' ' + Surname")]) for better readability.

Supported Expression Types:

  • ✅ Mathematical operations: +, -, *, /, %
  • ✅ Comparison: ==, !=, <, >, <=, >=
  • ✅ Logical: &&, ||, !
  • ✅ Ternary operator: condition ? true : false
  • ✅ String concatenation: +
  • ✅ Property access: Property.SubProperty
  • ✅ Method calls: Property.ToString()
  • ✅ Parentheses for grouping: (A + B) * C

Generated Code Example:

The generator creates highly optimized code like this:

// <auto-generated />
public partial class OrderEntity
{
    public static implicit operator OrderDto(OrderEntity entity)
    {
        if(entity == null) return null;
        return new OrderDto 
        {
            Price = entity.Price,
            Tax = entity.Tax,
            Discount = entity.Discount,
            NetTotal = entity.Price * (entity.Tax + 100) / 100 - entity.Discount,
            Name = entity.Name,
            Surname = entity.Surname,
            FullName = entity.Name + " " + entity.Surname,
            IsActive = entity.IsActive,
            StatusText = entity.IsActive ? "Active" : "Passive"
        };
    }
}

Zero reflection - just pure, optimized C# code!
Fully debuggable - set breakpoints and step through!
Type-safe - compile-time validation!


3. Nested and Collection Mapping

Scenario: Automatically map nested objects and collections.

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

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

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

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

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

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

        // Automatic nested collection mapping!
        OrderEntity entity = dto; 

        Console.WriteLine($"Order #{entity.OrderId} - {entity.CustomerName}");
        Console.WriteLine("Products:");
        foreach (var p in entity.Products)
            Console.WriteLine($"  {p.Code}: {p.Quantity}x @ ${p.Price}");
    }
}

Console Output:

Order #3 - Acme Corp
Products:
  A123: 2x @ $49.99
  B456: 5x @ $29.99

Nested objects mapped automatically!
Collections supported: List<T>, IEnumerable<T>, arrays, etc.
Deep nesting works recursively!


4. Debugging and Maintainability

All mapping code is standard C# and fully debuggable:

  1. View Generated Files:

    • Visual Studio: Solution Explorer → Dependencies → Analyzers → Chd.Mapping.Roslyn.Advanced
    • Or check obj/Debug/netX.X/generated/ folder
  2. Set Breakpoints:

    • Navigate to generated implicit operator methods
    • Step through mapping code line by line
    • Inspect variable values
  3. IntelliSense Support:

    • Full code completion
    • Navigate to definition (F12)
    • Find all references
    • Refactoring support

Example Generated Code:

public static implicit operator UserEntity(UserDto source)
{
    if (source == null) return null;
    return new UserEntity
    {
        Id = source.Id,
        FullName = source.Name,
        EmailAddress = source.Email
    };
}

Generated Code is:

  • ✅ Readable and maintainable
  • ✅ Optimized by the C# compiler
  • ✅ No runtime overhead
  • ✅ Type-safe at compile time

public string StatusText { get; set; }
public bool IsActive { get; set; }

}

class Program { static void Main() { OrderDto dto = new OrderDto() { Price = 100, Tax = 18, Discount = 2, Name = "Mehmet", Surname = "Yoldaş", IsActive = true }; OrderEntity entity = dto; dto = entity; Console.WriteLine($"NetTotal: {dto.NetTotal}"); // 116 Console.WriteLine($"FullName: {dto.FullName}"); // Mehmet Yoldaş Console.WriteLine($"StatusText: {dto.StatusText}"); // Active } }


**Console Output:**

NetTotal: 116 FullName: Mehmet Yoldaş StatusText: Active


> **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")]`.

---
**Generated Code Example:**

When building the above example, the generator creates code similar to this:
```csharp
// <auto-generated />

namespace Mapping.Test
{
    public partial class OrderEntity
    {
        public static implicit operator global::Mapping.Test.OrderDto(OrderEntity entity)
        {
            if(entity == null) return null;
            return new OrderDto {
                Price = entity.Price,
                Tax = entity.Tax,
                Discount = entity.Discount,
                NetTotal = entity.Price *(entity.Tax+100)/100 - entity.Discount,
                Name = entity.Name,
                Surname = entity.Surname,
                FullName = entity.Name + " " + entity.Surname,
                IsActive = entity.IsActive,
                StatusText = entity.IsActive ? "Active" : "Passive"
            };
        }
    }
}

Therefore, you can debug and step through the generated mapping logic as needed. Runtime performance is equivalent to hand-written code. There is no reflection or dynamic code involved.None of the mapping logic is executed at runtime; everything is pre-compiled. Runtime errors due to mapping issues are eliminated.

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 and 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.

Test Repository For Usage

This repository contains examples of how to use the Library.Mapping package in different scenarios, including DTO-Entity mapping, operator injection, and performance benchmarks.

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 108 2/28/2026
8.1.2 95 2/19/2026
8.1.1 240 1/28/2026
8.0.9 105 1/23/2026
8.0.7 110 1/21/2026
8.0.6 103 1/20/2026
8.0.5 98 1/20/2026
8.0.4 100 1/20/2026
8.0.3 104 1/20/2026
8.0.2 103 1/20/2026
8.0.1 100 1/19/2026