https://github.com/odinsoft-lab/simple.mapper
Simple.AutoMapper is a tool that automatically "copies data from one shape to another" within an app. Instead of manually moving the same information between database objects and view models, simple mapping rules can be defined once and quickly reused everywhere with precompiled mapping and caching.
https://github.com/odinsoft-lab/simple.mapper
compiled-mapping dto expression-trees list-mapping mapper mapping-engine object-mapping reflection-free
Last synced: about 2 months ago
JSON representation
Simple.AutoMapper is a tool that automatically "copies data from one shape to another" within an app. Instead of manually moving the same information between database objects and view models, simple mapping rules can be defined once and quickly reused everywhere with precompiled mapping and caching.
- Host: GitHub
- URL: https://github.com/odinsoft-lab/simple.mapper
- Owner: odinsoft-lab
- License: mit
- Created: 2025-08-20T08:06:51.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2026-01-10T19:57:20.000Z (about 2 months ago)
- Last Synced: 2026-01-11T05:53:37.637Z (about 2 months ago)
- Topics: compiled-mapping, dto, expression-trees, list-mapping, mapper, mapping-engine, object-mapping, reflection-free
- Language: C#
- Homepage:
- Size: 328 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: docs/CONTRIBUTING.md
- License: LICENSE.md
- Roadmap: docs/ROADMAP.md
Awesome Lists containing this project
README
# Simple.AutoMapper
[](https://www.nuget.org/packages/Simple.AutoMapper/)
[](https://dotnet.microsoft.com/)
[](LICENSE.md)
[](https://www.nuget.org/packages/Simple.AutoMapper/)
High-performance object mapping for .NET with expression tree compilation. Simple API, powerful configuration options.
> **v1.0.9** - Added Condition, NullSubstitute, BeforeMap/AfterMap, ConstructUsing. See [Release Notes](docs/releases/v1.0.9.md).
## Installation
```powershell
dotnet add package Simple.AutoMapper
```
**Target Frameworks:** netstandard2.0, netstandard2.1, net8.0, net9.0, net10.0
## Quick Start
```csharp
using Simple.AutoMapper.Core;
// Simple mapping - no configuration needed
var dto = Mapper.Map(user);
var dtos = Mapper.Map(users);
// In-place update
Mapper.Map(source, existingDestination);
```
## Configuration Options
### Basic Configuration
```csharp
// Configure mapping with options
Mapper.CreateMap()
.Ignore(d => d.Password)
.ReverseMap(); // Creates UserDto -> User mapping too
```
### ForMember with MapFrom
```csharp
Mapper.CreateMap()
.ForMember(d => d.FullName, opt => opt.MapFrom(s => $"{s.FirstName} {s.LastName}"))
.ForMember(d => d.Age, opt => opt.MapFrom(s => DateTime.Now.Year - s.BirthYear));
```
### Condition - Conditional Mapping
```csharp
Mapper.CreateMap()
.ForMember(d => d.Email, opt => {
opt.MapFrom(s => s.Email);
opt.Condition(s => s.IsEmailVerified); // Only map if condition is true
});
```
### NullSubstitute - Default Values
```csharp
Mapper.CreateMap()
.ForMember(d => d.DisplayName, opt => {
opt.MapFrom(s => s.Nickname);
opt.NullSubstitute("Anonymous"); // Use "Anonymous" if source is null
});
```
### BeforeMap / AfterMap - Callbacks
```csharp
Mapper.CreateMap()
.BeforeMap((src, dest) => {
// Execute before property mapping
dest.MappedAt = DateTime.UtcNow;
})
.AfterMap((src, dest) => {
// Execute after property mapping
dest.FullName = $"{dest.FirstName} {dest.LastName}";
});
```
### ConstructUsing - Custom Construction
```csharp
// For types without parameterless constructor
Mapper.CreateMap()
.ConstructUsing(src => new UserDto(src.Id));
// For immutable objects
Mapper.CreateMap()
.ConstructUsing(src => new ImmutableUserDto(
src.Id,
src.Name,
src.Email
));
```
### Circular Reference Handling
```csharp
Mapper.CreateMap()
.PreserveReferences() // Handle circular references
.MaxDepth(5); // Limit recursion depth
```
## Dependency Injection
```csharp
// In Program.cs or Startup.cs
services.AddSimpleMapper(cfg => {
cfg.AddProfile();
});
// Or scan assemblies
services.AddSimpleMapper(typeof(UserMappingProfile).Assembly);
```
### Creating Profiles
```csharp
public class UserMappingProfile : Profile
{
public UserMappingProfile()
{
CreateMap()
.ForMember(d => d.FullName, opt => opt.MapFrom(s => $"{s.FirstName} {s.LastName}"));
CreateMap
();
}
}
```
## EF Core Integration
### Read Operations
```csharp
// Materialize first, then map
var users = await db.Users
.AsNoTracking()
.Include(u => u.Address)
.ToListAsync();
var dtos = Mapper.Map(users);
```
### Write Operations
```csharp
// Create
var entity = Mapper.Map(dto);
await db.Users.AddAsync(entity);
// Update in-place
var entity = await db.Users.FindAsync(id);
Mapper.Map(dto, entity);
await db.SaveChangesAsync();
```
### Collection Sync
```csharp
var result = Mapper.Map(
dtoList,
entityList,
dto => dto.Id,
entity => entity.Id,
removeMissing: true
);
// result.Added, result.Updated, result.Removed
```
## Type Support
| Type | Support |
|------|---------|
| Simple types (int, string, DateTime, Guid, etc.) | ✅ |
| Nullable types | ✅ |
| Enums | ✅ |
| Complex types (classes) | ✅ Recursive |
| Collections (List, Array, IEnumerable) | ✅ |
| Circular references | ✅ With PreserveReferences() |
## Performance
- Expression tree compilation for fast subsequent mappings
- Thread-safe caching of compiled mappers
- First mapping incurs compilation cost; subsequent calls are optimized
## Samples & Tests
- See `samples/` for end-to-end usage examples
- See `tests/` for comprehensive test coverage including edge cases
## License
MIT License - see [LICENSE.md](LICENSE.md)
## Team
**Core Development Team**
- **SEONGAHN** - Lead Developer & Project Architect
- **YUJIN** - Senior Developer & Exchange Integration Specialist
- **SEJIN** - Software Developer & API Implementation
---
**Built with care by the ODINSOFT Team** | [GitHub](https://github.com/odinsoft-lab/simple.mapper)