VeloxMapper.Core
4.0.2
See the version list below for details.
dotnet add package VeloxMapper.Core --version 4.0.2
NuGet\Install-Package VeloxMapper.Core -Version 4.0.2
<PackageReference Include="VeloxMapper.Core" Version="4.0.2" />
<PackageVersion Include="VeloxMapper.Core" Version="4.0.2" />
<PackageReference Include="VeloxMapper.Core" />
paket add VeloxMapper.Core --version 4.0.2
#r "nuget: VeloxMapper.Core, 4.0.2"
#:package VeloxMapper.Core@4.0.2
#addin nuget:?package=VeloxMapper.Core&version=4.0.2
#tool nuget:?package=VeloxMapper.Core&version=4.0.2
VeloxMapper
VeloxMapper, modern .NET platformu (net8.0+) için tasarlanmış; performans, tip güvenliği ve gözlemlenebilirliği (observability) önceliklendiren, deterministik ve fail-fast (erken hata) tabanlı hibrit bir nesne eşleştirme (object mapping) kütüphanesidir.
Bu proje, AutoMapper gibi geleneksel kütüphanelerin sunduğu dinamik ve bazen "sürprizli" (implicit/black-box) davranışlar yerine; katı kuralları, derleme zamanı güvencelerini ve startup doğrulamasını merkeze alır. VeloxMapper ile yazılan haritalama kuralları asla belirsiz kalmaz; hata varsa uygulama ayağa kalkarken (fail-fast) tespit edilir.
🚀 Neden VeloxMapper?
- Fail-Fast (Startup Validation): Hatalı veya eksik eşleştirmeler, uygulama ayağa kalkarken yapılan doğrulama (
AssertConfigurationIsValid) ile hemen yakalanır. Üretim ortamında (production) beklenmedik çalışma zamanı hataları yaşamazsınız. - Çift Katmanlı (Hibrit) Motor:
- Layer 1 (Source Generator):
[VeloxMap]niteliğiyle işaretlenen sınıflar için derleme zamanında NativeAOT uyumlu, reflection içermeyen, allocation-free saf C# kodları üretir. - Layer 2 (Expression Tree): Dinamik senaryolarda haritalama planlarını çalışma zamanında bellekte bir kez derleyerek strongly-typed delegateler (
Func<TSource, TDest>) oluşturur ve önbelleğe alır.
- Layer 1 (Source Generator):
- Gözlemlenebilirlik (Observability): Haritalama planlarının ne yaptığını ve hangi özelliğin hangi yöntemle eşleştiğini gösteren JSON/Text raporları üretebilir. Bu raporların SHA-256 hash çıktısını CI/CD süreçlerinizde snapshot testleri ile doğrulayarak eşleştirme kurallarının kazara bozulmasını önleyebilirsiniz.
- AutoMapper Kolay Geçiş Desteği:
VeloxProfile,CreateMap<A, B>(),ForMember,MapFrom,Ignoreve otomatik profile scanning (assembly tarama) yetenekleri sayesinde AutoMapper kullanan projelerinizi minimum eforla VeloxMapper'a geçirebilirsiniz.
📦 Kurulum
VeloxMapper, analyzer bileşeni entegre edilmiş tek bir paket olarak kurulur. Source Generator arka planda otomatik devreye girer.
dotnet add package VeloxMapper
Not: VeloxMapper, Entity Framework veya harici başka bir paket bağımlılığı taşımaz. Sadece saf .NET API'leri üzerine kuruludur.
🛠️ Temel Yapılandırma ve Profil Sistemi
VeloxMapper v4.0.1 ile haritalama tanımlarınızı organize etmek için AutoMapper benzeri Profil (Profile) yapısı getirilmiştir.
1. Haritalama Profili Tanımlama
VeloxProfile sınıfından türeyen bir profil oluşturun ve eşleştirmelerinizi yapıcı metot (constructor) içerisinde tanımlayın:
using VeloxMapper.Configuration;
public class UserMappingProfile : VeloxProfile
{
public UserMappingProfile()
{
// Temel eşleştirme (Property isimleri case-insensitive olarak otomatik eşleşir)
CreateMap<AddressSource, AddressDest>();
// Custom kurallar içeren eşleştirme
CreateMap<UserSource, UserDest>()
// ForMember + MapFrom ile özel değer atama
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"))
// ForMember + Ignore ile bir alanı eşleştirme dışı bırakma
.ForMember(dest => dest.SecretToken, opt => opt.Ignore());
// Otomatik Ters Yön Eşleştirme (ReverseMap)
CreateMap<CompatibilitySource, CompatibilityDest>().ReverseMap();
// Özel Nesne Yaratımı (ConstructUsing)
CreateMap<FactorySource, FactoryDest>()
.ConstructUsing(src => new FactoryDest(src.Name + "_Custom"));
// Tüm Özelliklere Toplu Kurallar (ForAllMembers)
CreateMap<CompatibilitySource, CompatibilityDest>()
// Örneğin: Sadece null olmayan değerleri hedef özelliklere ata
.ForAllMembers(opt => opt.Condition((src, dest, val) => val != null));
}
}
2. Bağımsız Kullanım (DI Olmadan)
Haritalama profillerinizi MapperConfiguration sınıfına kaydedin ve ardından Mapper sınıfını oluşturun:
using VeloxMapper;
using VeloxMapper.Configuration;
// 1. Konfigürasyonu tanımlayın
var config = new MapperConfiguration(cfg =>
{
// Profili ekleyin
cfg.AddProfile<UserMappingProfile>();
// Veya birden fazla profili inline ekleyebilirsiniz
// cfg.CreateMap<SourceModel, DestModel>();
});
// 2. Fail-Fast doğrulamayı çalıştırın (ÖNERİLEN: Startup veya Test aşamasında)
config.AssertConfigurationIsValid();
// 3. Mapper instance'ını oluşturun
var mapper = new Mapper(config);
3. Dependency Injection (DI) ve Assembly Scanning
ASP.NET Core uygulamalarınızda haritaları ve profilleri otomatik taratarak IoC konteynerine kaydetmek için AddVeloxMapper extension metodunu kullanabilirsiniz.
// Program.cs
using VeloxMapper.DependencyInjection;
builder.Services.AddVeloxMapper(cfg =>
{
// Belirtilen Assembly içindeki tüm VeloxProfile sınıflarını otomatik tarar ve yükler
cfg.AddProfilesFromAssembly(typeof(UserMappingProfile).Assembly);
// Patch haritalama davranışında kaynak null ise hedef değerin korunmasını ayarlar (opsiyonel)
cfg.PatchMapping.IgnoreNullValues = true;
});
AddVeloxMapper metodu, aşağıdaki singleton servisleri otomatik olarak kaydeder:
MapperConfiguration(Uygulama ayağa kalkarken doğrulamayı otomatik yapar)IVeloxMapper(İş parçacığı güvenli - Thread-Safe haritalama arayüzü)
Kullanım örneği:
public class UserService
{
private readonly IVeloxMapper _mapper;
public UserService(IVeloxMapper mapper)
{
_mapper = mapper;
}
public UserDest Execute(UserSource source)
{
// TSource ve TDest belirterek haritalama yapın
return _mapper.Map<UserSource, UserDest>(source);
// Veya daha kısa biçimde hedef türü belirtin (kaynak tür runtime'da çözümlenir)
// return _mapper.Map<UserDest>(source);
}
}
⚡ Haritalama Yetenekleri
VeloxMapper, tip dönüşümlerinde ortaya çıkabilecek uyumsuzlukları gidermek için gelişmiş tip çözümleme mimarisine sahiptir.
1. Düzleştirme (Flattening)
Kaynak nesnedeki iç içe geçmiş (nested) POCO nesnelerinin property'lerini, hedefteki düz (flat) property'lere otomatik olarak eşler.
- Kural:
Source.NestedObject.Property➡️Dest.NestedObjectProperty
public class Address { public string City { get; set; } }
public class CustomerSource { public Address Address { get; set; } }
public class CustomerDest { public string AddressCity { get; set; } }
// Profilde CreateMap<CustomerSource, CustomerDest>() yazılması yeterlidir.
// Address.City değeri otomatik olarak AddressCity alanına atanır.
2. Koleksiyon Haritalama (Collection Mapping)
VeloxMapper; List<T>, T[], IEnumerable<T>, ICollection<T> ve IList<T> koleksiyon tipleri arasında otomatik eleman eşleştirmesi ve dönüştürmesi yapar.
public class OrderSource { public List<ItemSource> Items { get; set; } }
public class OrderDest { public ItemDest[] Items { get; set; } }
// Items içindeki ItemSource nesneleri, profilde tanımlı ItemSource -> ItemDest
// eşleştirmesine göre dönüştürülerek hedef diziye (array) atanır.
3. Nullable Tipler (Nullable Wrapping & Unwrapping)
Nullable ve non-nullable yapılar arasındaki geçişleri güvenli bir şekilde yönetir:
int?➡️int: Kaynak null ise hedefe türün varsayılan değeri (default) yazılır.int➡️int?: Değer nullable yapıya güvenle sarılır.int?➡️double?: Farklı underlying tipler arasındaki nullable dönüşümleri de otomatik olarak halledilir.
4. Enum Dönüşümleri (Enum Mapping)
Farklı enum tipleri veya enum-ilkel tipler arasında güvenli dönüşüm sağlar:
SourceEnum➡️DestEnum: Enum'ların sayısal (underlying) değerleri üzerinden dönüştürülür.Enum➡️string: Otomatik.ToString()çağrısı yapılır.string➡️Enum: OtomatikEnum.Parse(case-insensitive) çağrısı yapılır.
5. Özel Tip Dönüştürücüler (IVeloxTypeConverter)
Daha karmaşık veya dış kütüphanelerden gelen tiplerin dönüşümleri için kendi dönüştürücü sınıfınızı tanımlayabilirsiniz:
using VeloxMapper.Abstractions;
// 1. Dönüştürücü sınıfınızı oluşturun
public class DateTimeToStringConverter : IVeloxTypeConverter<DateTime, string>
{
public string Convert(DateTime source)
{
return source.ToString("yyyy-MM-dd HH:mm:ss");
}
}
// 2. Profilde veya konfigürasyonda bunu kaydedin
public class MyProfile : VeloxProfile
{
public MyProfile()
{
CreateMap<DateTime, string>().ConvertUsing(new DateTimeToStringConverter());
}
}
🚀 Çift Katmanlı (Layered) Çalışma Mantığı
VeloxMapper'ı benzersiz kılan, derleme zamanı ile çalışma zamanını birleştiren hibrit yapısıdır.
Layer 1: Source Generator (NativeAOT & Zero Allocation)
Eğer sınıfınızı [VeloxMap] attribute'u ile işaretlerseniz, Roslyn derleme zamanında doğrudan kaynak kod üretir. Bu sayede hiçbir reflection ve runtime yükü olmadan, statik extension metotlar üzerinden haritalama yapabilirsiniz.
using VeloxMapper.Attributes;
[VeloxMap(typeof(UserSource), typeof(UserDest))]
public class UserSource
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
// Derleyicinin arka planda ürettiği extension metot doğrudan kullanılabilir:
var source = new UserSource { FirstName = "Ali", LastName = "Yılmaz" };
UserDest dest = source.MapToUserDest(); // Sıfır reflection, maksimum hız!
Layer 2: Runtime Expression Tree Engine
[VeloxMap] ile işaretlenmemiş sınıflar için dinamik plan çıkarılır. Expression Tree mimarisi kullanılarak bir kez strongly-typed delegate derlenir ve önbelleğe alınır. Sonraki haritalamalarda doğrudan bu compiled delege çağrıldığı için performans geleneksel reflection tabanlı mapper'lara göre katbekat yüksektir.
🔍 EF Core Projeksiyon Desteği (ProjectTo)
Veritabanından DTO çekerken performans kaybı yaşamamak için ProjectTo yeteneğini kullanabilirsiniz. VeloxMapper, Expression Tree planını doğrudan EF Core veritabanı sorgusuna (SQL SELECT ifadesine) dönüştürür.
using VeloxMapper.Extensions;
public List<UserDto> GetUserDtos(MyDbContext dbContext, IVeloxMapper mapper)
{
return dbContext.Users
.ProjectTo<UserDto>(mapper) // IQueryable üzerine yazar
.ToList(); // SQL SELECT Id, FullName... şeklinde veritabanında çalıştırılır
}
Güvenlik Sınırı: VeloxMapper, EF Core'un destekleyemediği ve veritabanında çalıştırılamayacak kullanıcı tanımlı metot çağrılarını projeksiyon planlarında reddeder ve erken hata (VeloxProjectionException) fırlatır. Bu durum, veritabanına sorgu atılmadan önce hatalı sorguları yakalamanızı sağlar.
📈 Gözlemlenebilirlik (Observability) & Snapshot Testleri
VeloxMapper, büyük ölçekli ve kurumsal projelerde haritalama şemalarındaki değişiklikleri CI/CD süreçlerinde izlemek için deterministik hash desteği sunar. Haritalama planları (MappingPlanDef) üzerinden SHA-256 hash'leri üreterek şema değişikliklerini test edebilirsiniz.
using VeloxMapper.Diagnostics;
using VeloxMapper.Configuration;
// 1. Konfigürasyon üzerinden ilgili eşleştirmenin harita planını (MappingPlanDef) alın
var plan = config.GetMappingPlan(typeof(UserSource), typeof(UserDest));
// 2. Okunabilir metin veya JSON raporu üretin
string readablePlanText = MappingPlanReport.GenerateTextReport(plan);
string rawJsonPlan = MappingPlanReport.GenerateJsonReport(plan);
// 3. Deterministik şema hash'ini alın (SHA-256)
string planHash = MappingPlanReport.GenerateHash(plan);
Snapshot Testi Yazma Örneği (xUnit)
Bu yöntemle, bir geliştirici kazara DTO property ismini değiştirdiğinde veya eşleştirmeyi bozduğunda CI pipeline'ınız hata vererek testi kıracaktır:
[Fact]
public void MappingPlans_ShouldMatch_ApprovedSnapshot()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<UserMappingProfile>();
});
// Planı konfigürasyondan alıyoruz
var plan = config.GetMappingPlan(typeof(UserSource), typeof(UserDest));
string currentHash = MappingPlanReport.GenerateHash(plan);
string expectedHash = "ff1f514ac56ca5be76cf0339013e2b49a7725f2696cf249b62bdc43f1b49b8e6"; // Önceden onaylanmış hash
Assert.Equal(expectedHash, currentHash);
}
🔄 AutoMapper'dan Geçiş Kılavuzu (Migration Guide)
AutoMapper kullanan mevcut projenizi VeloxMapper'a geçirmek oldukça basittir. Aşağıdaki tablo, temel kavramların karşılıklarını göstermektedir:
| AutoMapper Karşılığı | VeloxMapper Karşılığı | Açıklama |
|---|---|---|
Profile |
VeloxProfile |
Harita profillerinin tanımlandığı temel sınıf. |
CreateMap<TSource, TDest>() |
CreateMap<TSource, TDest>() |
Eşleştirme kaydı başlatır. |
.ForMember(dest => dest.X, opt => opt.MapFrom(src => ...)) |
.ForMember(dest => dest.X, opt => opt.MapFrom(src => ...)) |
Özel üye atamaları (Fluent API). |
.ForMember(dest => dest.X, opt => opt.Ignore()) |
.ForMember(dest => dest.X, opt => opt.Ignore()) |
Bir property'yi eşleme dışı bırakma. |
IMapper |
IVeloxMapper |
Dependency Injection için servis arayüzü. |
MapperConfiguration |
MapperConfiguration |
Konfigürasyon ve startup doğrulaması için sınıf. |
cfg.AddMaps(...) veya AddProfiles(...) |
cfg.AddProfilesFromAssembly(...) |
Assembly içindeki profilleri otomatik tarama. |
mapper.ProjectTo<TDest>(queryable) |
queryable.ProjectTo<TDest>(mapper) |
EF Core sorgu projeksiyonu. |
ReverseMap() |
ReverseMap() |
Otomatik ters yön (TDestination → TSource) eşleştirmesi kaydeder. |
ConstructUsing(src => ...) |
ConstructUsing(src => ...) |
Nesne yaratılırken kullanılacak özel factory delegesi tanımlar. |
ForAllMembers(opt => opt.Ignore()) |
ForAllMembers(opt => opt.Ignore()) |
Tüm hedef özellikleri eşleme dışı bırakır. |
ForAllMembers(opt => opt.Condition((src, dest, val) => ...)) |
ForAllMembers(opt => opt.Condition((src, dest, val) => ...)) |
Her özellik eşlemesinden önce değerlendirilecek global bir koşul tanımlar. |
Adım Adım Geçiş Örneği
1. AutoMapper ile Yazılmış Eski Kod
// ❌ ESKİ AUTOMAPPER KODU
using AutoMapper;
public class OldUserProfile : Profile
{
public OldUserProfile()
{
CreateMap<Address, AddressDto>();
CreateMap<User, UserDto>()
.ForMember(d => d.FullName, o => o.MapFrom(s => s.FirstName + " " + s.LastName))
.ForMember(d => d.SecretKey, o => o.Ignore());
}
}
2. VeloxMapper ile Yeni Kod
Sadece kütüphane namespace'lerini ve temel sınıf adını güncelleyerek haritanızı birebir taşıyın:
// YENİ VELOXMAPPER KODU
using VeloxMapper.Configuration;
public class NewUserProfile : VeloxProfile
{
public NewUserProfile()
{
CreateMap<Address, AddressDto>();
CreateMap<User, UserDto>()
.ForMember(d => d.FullName, o => o.MapFrom(s => $"{s.FirstName} {s.LastName}"))
.ForMember(d => d.SecretKey, o => o.Ignore());
}
}
3. DI Servis Kaydı Güncellemesi
// Program.cs - AutoMapper Kaydı (Eski)
// builder.Services.AddAutoMapper(typeof(Program));
// Program.cs - VeloxMapper Kaydı (Yeni)
builder.Services.AddVeloxMapper(cfg =>
{
cfg.AddProfilesFromAssembly(typeof(Program).Assembly);
});
🛡️ Hata Tipleri (Exception Reference)
VeloxMapper'da oluşan tüm hatalar VeloxException tabanlıdır. Kök nedenlerine göre sınıflara ayrılmıştır:
VeloxConfigurationException: Yapılandırma hatalarında fırlatılır (örn. startup doğrulamasıAssertConfigurationIsValidbaşarısız olduğunda veya aynı tip çifti için birden fazla özel converter kaydedildiğinde).VeloxMappingException: Çalışma zamanında haritalama işlemi esnasında oluşabilecek olağan dışı tür uyuşmazlığı hatalarında fırlatılır.VeloxProjectionException:ProjectToiçinde EF Core veya veritabanı tarafından desteklenmeyecek geçersiz bir expression (örn. C# custom metot çağrısı) tespit edildiğinde fırlatılır.VeloxAmbiguousConstructorException: Hedef sınıfta birden fazla constructor bulunup hangisinin kullanılacağı belirsiz olduğunda fırlatılır (Çözüm için[VeloxConstructor]attribute'unu kullanın).
📈 Performans ve Tasarım Kararları
VeloxMapper, maksimum performansa odaklanmıştır:
- No DynamicInvoke: Üretilen expression delegeleri doğrudan strongly-typed
Invokeedilerek dynamic invoke maliyetlerinden kaçınılır. - No Runtime Reflection (for Generator): Source Generator ile üretilen kodlar tamamen C# atama satırlarından oluşur. NativeAOT ile tamamen uyumludur ve sıfır allocation ile çalışır.
- Immutable Configuration: Konfigürasyon uygulaması ayağa kalktıktan sonra tamamen kilitlenir (frozen/immutable). Çalışma zamanında yeni harita ekleme/çıkarma yapılamaz, bu da thread contention ve lock senaryolarını sıfıra indirir.
📄 Lisans
Bu proje MIT Lisansı ile lisanslanmıştır. Kurumsal ve bireysel projelerinizde ücretsiz olarak güvenle kullanabilirsiniz.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.