A very lightweight C# object mapper with a fluent API that supports basic mapping, conditional mapping, and combine mapping. The library is designed to be readable, small, and efficient.
- 🌮 Basic Property Mapping - Auto-map properties with matching names and types
- 🌯 Custom Transformations - Transform values during mapping
- 🥙 Conditional Mapping - Map properties based on conditions
- 🌮 Combine Mapping - Combine multiple source properties into one destination property
- 🔥 Fluent API - Chain mapping configurations for readability
- 📦 Collection Support - Map collections of objects
- 🚫 Ignore Properties - Skip specific properties during mapping
- ⚡ Lightweight - Minimal dependencies and small footprint
// Simple mapping for properties with matching names and types
var personDto = ObjectMapper.Map<Person, PersonDto>(person);var mapper = ObjectMapper.Create<Person, PersonDto>()
.Map(dest => dest.Id, src => src.Id)
.Map(dest => dest.Email, src => src.Email)
.Map(dest => dest.Age, src => src.DateOfBirth, dob => DateTime.Now.Year - dob.Year)
.Map(dest => dest.Status, src => src.IsActive, active => active ? "Active" : "Inactive")
.Combine(dest => dest.FullName, src => $"{src.FirstName} {src.LastName}");
var result = mapper.MapFrom(person);var mapper = ObjectMapper.Create<Person, PersonDto>()
.Map(dest => dest.Id, src => src.Id)
.MapIf(dest => dest.SalaryFormatted,
src => src.Salary,
salary => $"${salary:N2}",
src => src.IsActive) // Only map salary if person is active
.Combine(dest => dest.FullName, src => $"{src.FirstName} {src.LastName}");var mapper = ObjectMapper.Create<Address, AddressDto>()
.Map(dest => dest.Street, src => src.Street)
.Map(dest => dest.City, src => src.City)
.Map(dest => dest.ZipCode, src => src.ZipCode)
.Combine(dest => dest.FormattedAddress,
src => $"{src.Street}, {src.City} {src.ZipCode}");var mapper = ObjectMapper.Create<Person, PersonDto>()
.Map(dest => dest.Id, src => src.Id)
.Ignore(dest => dest.Email) // Skip email mapping
.Combine(dest => dest.FullName, src => $"{src.FirstName} {src.LastName}");var people = new List<Person> { /* ... */ };
// Using configured mapper
var mapper = ObjectMapper.Create<Person, PersonDto>()
.Map(dest => dest.Id, src => src.Id)
.Combine(dest => dest.FullName, src => $"{src.FirstName} {src.LastName}");
var results = mapper.MapFrom(people);
// Or simple auto-mapping
var simpleResults = ObjectMapper.Map<Person, PersonDto>(people);Create<TSource, TDestination>()- Creates a new mapper instanceMap<TSource, TDestination>(source)- Simple auto-mapping for single objectMap<TSource, TDestination>(sources)- Simple auto-mapping for collections
Map(dest, src)- Basic property mappingMap(dest, src, transform)- Property mapping with transformationMapIf(dest, src, condition)- Conditional property mappingMapIf(dest, src, transform, condition)- Conditional mapping with transformationCombine(dest, combineFunction)- Combine multiple source propertiesIgnore(dest)- Ignore a destination propertyMapFrom(source)- Execute mapping on single objectMapFrom(sources)- Execute mapping on collection
The mapper uses:
- Reflection for auto-mapping properties with matching names and types
- Expression trees for fluent property selection
- Compiled delegates for efficient property access and transformations
- Dictionary-based caching for mapping configurations
- Clean architecture with organized core components
- Mappers are reusable - create once, use many times
- Compiled expressions provide good performance after first use
- Auto-mapping uses reflection, so explicit mapping is faster for hot paths
- Small memory footprint with minimal allocations
- .NET 8.0 or later
- C# 12.0 language features
MIT License