Attribute Mapper ([MapTo])
EggMapper.Generator generates zero-reflection, zero-allocation extension methods at build time from a single [MapTo] attribute. No MapperConfiguration, no runtime delegates — the mapping code is emitted directly into your binary.
Installation
dotnet add package EggMapper.Generator
The generator package automatically injects the
[MapTo],[MapProperty], and[MapIgnore]attributes into your compilation — no separate abstractions package needed.
Basic Usage
1 — Annotate the source class
using EggMapper;
[MapTo(typeof(OrderDto))]
public class Order
{
public int Id { get; set; }
public string CustomerName { get; set; } = "";
public decimal Total { get; set; }
}
public class OrderDto
{
public int Id { get; set; }
public string CustomerName { get; set; } = "";
public decimal Total { get; set; }
}
2 — Use the generated extension method
var order = new Order { Id = 1, CustomerName = "Alice", Total = 99.99m };
OrderDto dto = order.ToOrderDto(); // generated extension method
List<OrderDto> dtos = orders.ToOrderDtoList(); // generated list method
No mapper instance, no DI registration, no startup cost.
Multiple Destinations
Apply [MapTo] multiple times to map a single source to several destinations:
[MapTo(typeof(OrderDto))]
[MapTo(typeof(OrderSummary))]
public class Order { ... }
Generates ToOrderDto(), ToOrderDtoList(), ToOrderSummary(), and ToOrderSummaryList().
Renaming Properties ([MapProperty])
[MapTo(typeof(CustomerDto))]
public class Customer
{
public int Id { get; set; }
[MapProperty("FullName")] // maps Customer.Name → CustomerDto.FullName
public string Name { get; set; } = "";
}
Ignoring Properties ([MapIgnore])
[MapTo(typeof(CustomerDto))]
public class Customer
{
public int Id { get; set; }
public string Name { get; set; } = "";
[MapIgnore]
public string Password { get; set; } = ""; // not copied to CustomerDto
}
Post-Map Hook (AfterMap)
Declare a partial static method to run custom logic after the generated initializer:
// In a separate file (user-authored):
public static partial class OrderToOrderDtoExtensions
{
static partial void AfterMap(Order source, OrderDto dest)
{
dest.DisplayName = $"#{source.Id} — {source.CustomerName}";
}
}
The generated ToOrderDto() calls AfterMap(source, dest) after building the object.
Diagnostics
| Code | Severity | Description |
|---|---|---|
| EGG2001 | Error | A destination property has no matching source member |
| EGG2002 | Info | An implicit type conversion was applied |
When to Use Attribute Mapper vs Runtime EggMapper
| Scenario | Recommendation |
|---|---|
| Simple 1:1 property copying, no custom logic | Attribute Mapper — zero overhead, compile-time safety |
Complex conditional mapping, BeforeMap/AfterMap hooks | Runtime EggMapper |
Need ForMember, ConvertUsing, MaxDepth | Runtime EggMapper |
| Want type errors at build time, not runtime | Attribute Mapper |