Fleksibel, intuitif, dan performa tinggi untuk object mapping di .NET
AIMapper adalah library object-to-object mapping untuk .NET 8 yang mendukung konfigurasi berbasis atribut maupun fluent interface.
Dirancang sebagai alternatif ringan AutoMapper, AIMapper mendukung:
- Flattening & unflattening properti nested
- Mapping berbasis atribut
[Map]
- Konfigurasi fluent (
cfg.ForMember(...)
) - Null substitute, converter, condition, ignore
- Paging async dan collection projection
- ReverseMap dan mapping profile terpusat
- Tanpa konfigurasi runtime
dotnet add package AIMapper
public class User {
public int Id { get; set; }
public string? Name { get; set; }
public UserProfile? Profile { get; set; }
}
public class UserProfile {
public string? Address { get; set; }
}
public class UserDto {
public int Id { get; set; }
public string? Name { get; set; }
public string? Address { get; set; }
}
services.AddAIMapper();
mapper.Configure<User, UserDto>(cfg => {
cfg.ForMember("Address", o => o.CustomPath = "Profile.Address");
});
var dto = mapper.Map<User, UserDto>(user);
var dtos = users.ProjectTo<User, UserDto>(mapper).ToList();
Fitur | Contoh |
---|---|
Ignore | cfg.ForMember("Name", o => o.Ignore()); |
CustomPath | cfg.ForMember("Address", o => o.CustomPath = "Profile.Address"); |
Condition | cfg.ForMember("IsActive", o => o.Condition<User, UserDto>((src, dest) => src.Status == StatusEnum.Active)); |
NullSubstitute | cfg.ForMember("Email", o => o.NullSubstitute("default@email.com")); |
ValueConverter | cfg.ForMember("Registered", o => o.ConvertUsing<DateTime?, string?>(dt => dt?.ToString("yyyy-MM-dd"))); |
BeforeMap / AfterMap | cfg.BeforeMap(...); cfg.AfterMap(...); |
ReverseMap | cfg.ReverseMap((Mapper)mapper); |
Paging Async | var pageDto = await users.ProjectToPagedListAsync<User, UserDto>(mapper, 1, 10); |
public class UserProfileMap : MapperProfile
{
public override void Configure(IMapper mapper)
{
mapper.Configure<User, UserDto>(cfg =>
{
cfg.ForMember("Address", o => o.CustomPath = "Profile.Address");
cfg.ForMember("Email", o => o.NullSubstitute("default@email.com"));
cfg.ForMember("Registered", o => o.ConvertUsing<DateTime?, string?>(dt => dt?.ToString("yyyy-MM-dd")));
cfg.ForMember("IsActive", o => o.Condition<User, UserDto>((src, dest) => src.Status == StatusEnum.Active));
cfg.ForMember("Name", o => o.Ignore());
cfg.BeforeMap((src, dest) => dest.Point = src.Point ?? 0);
cfg.AfterMap((src, dest) => dest.Name = src.Name?.ToUpper());
cfg.ReverseMap((Mapper)mapper);
});
mapper.Configure<Order, OrderDto>(cfg =>
{
cfg.ForMember("CustomerName", o => o.CustomPath = "Customer.Name");
cfg.ForMember("Total", o => o.NullSubstitute(0));
cfg.AfterMap((src, dest) => dest.IsPaid = src.Status == OrderStatus.Paid);
cfg.ReverseMap((Mapper)mapper);
});
}
}
mapper.ApplyProfilesFromCurrentAssembly();
Lihat AIMapperSampleDemo.cs
di project AIMapper.SampleApp untuk contoh implementasi penuh.
- π Instalasi & Registrasi
- π§ Basic Mapping
- ποΈ Custom Mapping (ForMember)
- π¦ Flattening Otomatis
- β³οΈ Override Flattening
- π Reverse Mapping
- π Collection Mapping
- π LINQ Projection (
ProjectTo
) - π§° Extension Method
.MapTo<T>()
- βοΈ Global Configuration
- π οΈ Manual Mapper (tanpa DI)
- π« Ignore Property
- β Validasi Mapping
- π§ Source Generator +
MapAttribute
- π Struktur & Debug Source Generator
dotnet add package AIMapper
services.AddAIMapper(typeof(MyMapperProfile).Assembly);
var dto = mapper.Map<PersonDto>(person);
cfg.CreateMap<Person, PersonDto>()
.ForMember(dest => dest.AddressCity, opt => opt.MapFrom(src => src.Address.City));
public class PersonDto
{
public string AddressCity { get; set; }
}
Jika Person.Address.City
ada, maka AddressCity
akan otomatis terisi.
Gunakan .ForMember(...).MapFrom(...)
untuk override flattening otomatis.
cfg.CreateMap<Person, PersonDto>().ReverseMap();
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(people);
var dtos = dbContext.People.ProjectTo<PersonDto>(mapper);
var dto = person.MapTo<PersonDto>();
services.AddAIMapper(cfg =>
{
cfg.NullSubstitution = "-";
cfg.IgnoreUnmapped = true;
});
var config = new MapperConfigurationExpression();
config.CreateMap<Person, PersonDto>();
var mapper = new Mapper(config);
.ForMember(dest => dest.IgnoredField, opt => opt.Ignore());
mapper.Configuration.AssertConfigurationIsValid();
public class PersonDto
{
[Map(Source = "Name")]
[Map(NullSubstitute = "Unknown")]
[Map(Condition = "x => !string.IsNullOrWhiteSpace(x)")]
[Map(Converter = "x => x.ToUpperInvariant()")]
public string DisplayName { get; set; }
}
Proyek ini menggunakan lisensi MIT License.